in

Dot Net Mafia

Group site for developer blogs dealing with (usually) .NET, SharePoint 2013, SharePoint 2010, Office 365, SharePoint Online, and other Microsoft products, as well as some discussion of general programming related concepts.

This Blog

Syndication

Archives

Corey Roth [MVP]

A SharePoint MVP bringing you the latest time saving tips for SharePoint 2013, Office 365 / SharePoint Online and Visual Studio 2013.

How to: Query Search using the Web Service

According to FeedBurner, my posts on querying Enterprise Search with the FullTextSqlQuery and KeywordQuery classes have been some of the most popular.  So I thought, I would continue on these posts and explain how to do it using the web service.  The SDK covers this, but not in enough detail for me.  When I am learning something new, I like to see complete examples, so hopefully this will help someone trying to learn how to do this.  The first place to start is by adding a web reference to your project.  You can query SharePoint Search or Enterprise Search in the exact same manner it is just a matter of which web service you make a reference to.  SharePoint search can be queried at a URL similar to the one below.

http://moss-server/_vti_bin/spsearch.asmx

To query Enterprise Search, the URL will look similar to this.  Both web services have the same methods.  They just query different indexes.

http://moss-server/_vti_bin/search.asmx

To execute a query, you have to build an XML document. I posted about the XML you post to the service in the past, now I will give a complete example and then also explain some of the options you can configure when querying.   The type of query is specified on the QueryText element using the Type attribute.  A value of MSSQLFT like in the XML below is used to do a full text query.

<QueryPacket xmlns="urn:Microsoft.Search.Query" Revision="1000">

  <Query domain="QDomain">

    <SupportedFormats>

      <Format>urn:Microsoft.Search.Response.Document.Document</Format>

    </SupportedFormats>

    <Context>

      <QueryText language="en-US" type="MSSQLFT">SELECT Title, Path, Description, Write, Rank, Size FROM Scope() WHERE CONTAINS('Accounting') AND "Scope" = 'Corporate Documents'</QueryText>

    </Context>

  </Query>

</QueryPacket>

In the example above, I have a simple query that is looking for documents with the word Accounting in the Corporate Documents scope.  Issuing a keyword query is similar but it uses a Type of STRING.  In this example, we are searching on the managed property city with a value of Austin.

<QueryPacket xmlns="urn:Microsoft.Search.Query" Revision="1000">

  <Query domain="QDomain">

    <SupportedFormats>

      <Format>urn:Microsoft.Search.Response.Document.Document</Format>

    </SupportedFormats>

    <Context>

      <QueryText language="en-US" type="STRING">City:"Austin"</QueryText>

    </Context>

  </Query>

</QueryPacket>

There are two methods used to query search.  The Query method returns the results as XML.  The QueryEx method returns the results as an ADO.NET dataset.  They both take the same input XML document like the ones above.  The code is pretty simple. Here I create a new reference to the web service (I named it QueryWebService) and I pass it credentials.  Like any SharePoint web service, you have to pass it credentials.  You can specify custom ones or just use the credentials of the application you are running using DefaultCredentials.

QueryWebService.QueryService queryService = new QueryWebService.QueryService();

queryService.Credentials = System.Net.CredentialCache.DefaultCredentials;

For this example, I am just going to build the input XML using a StringBuilder. 

queryXml.Append("<QueryPacket xmlns=\"urn:Microsoft.Search.Query\" Revision=\"1000\">");

queryXml.Append("<Query domain=\"QDomain\">");

queryXml.Append("<SupportedFormats>");

queryXml.Append("<Format>");

queryXml.Append("urn:Microsoft.Search.Response.Document.Document");

queryXml.Append("</Format>");

queryXml.Append("</SupportedFormats>");

queryXml.Append("<Range>");

queryXml.Append("<Count>50</Count>");

queryXml.Append("</Range>");

queryXml.Append("<Context>");

queryXml.Append("<QueryText language=\"en-US\" type=\"STRING\">");

queryXml.Append("City:\"Austin\"");

queryXml.Append("</QueryText>");

queryXml.Append("</Context>");

queryXml.Append("</Query>");

queryXml.Append("</QueryPacket>");

This query is similar to the one from above, but I added a Range and Count element.  By default, you will only get 10 results back, by changing this element I will get back 50 in this case.  You can also specify a StartAt element to start on a specific row.  This would be useful if you are building paging into something.  Then I just execute the query like so.

string resultXml = queryService.Query(queryXml.ToString());

This returns an XML document that looks similar to the following.

<ResponsePacket xmlns="urn:Microsoft.Search.Response">

  <Response domain="QDomain">

    <Range>

      <StartAt>1</StartAt>

      <Count>10</Count>

      <TotalAvailable>7312</TotalAvailable>

      <Results>

        <Document relevance="1000" xmlns="urn:Microsoft.Search.Response.Document">

          <Title>Document 1</Title>

          <Action>

            <LinkUrl size="0">http://moss-server/Documents/Document1.docx</LinkUrl>

          </Action>

          <Description />

          <Date>2008-07-15T19:59:43.2511787-05:00</Date>

        </Document>

        <Document relevance="1000" xmlns="urn:Microsoft.Search.Response.Document">

          <Title>Document 2</Title>

          <Action>

            <LinkUrl size="0">http://moss-server/Documents/Document2.docx</LinkUrl>

          </Action>

          <Description />

          <Date>2008-07-15T19:59:43.2511787-05:00</Date>

        </Document>

      </Results>

    </Range>

    <Status>SUCCESS</Status>

  </Response>

</ResponsePacket>

From here, you have something that you can easily work with using LINQ to XML.  If you are feeling lazy, you can always just use QueryEx to get a dataset as well.  You can configure quite a few options in how things are searched using the input XML document.  The schema is in the SDK if you are interested.  Hopefully, this will help the next time you need to query search.

Comments

 

Links (7/17/2008) « Steve Pietrek - Everything SharePoint said:

Pingback from  Links (7/17/2008) &laquo; Steve Pietrek - Everything SharePoint

July 17, 2008 8:42 PM
 

Bookmarking the web - w29/2008 - double density design said:

Pingback from  Bookmarking the web - w29/2008 - double density design

July 22, 2008 1:08 AM
 

andremt said:

Hi. i have a doubt about this post

You pass xml to a string, and my question is how i can put credentials in that string?

Because without the credentials, with that string i get error 401.

I have somehow attach the credentials

Thanks

André

November 5, 2008 4:01 AM
 

CoreyRoth said:

You have to provide credentials to the web service.  This line uses the credentials of the current account.  queryService.Credentials = System.Net.CredentialCache.DefaultCredentials;

You can also specify your own credentials if necessary.

November 10, 2008 10:52 AM
 

andremt said:

yes, but i am trying acess from buddyscript (building an agent), and there is not possible have this lines. So i need to put that credentials in the string. is possible?

Thanks for reply

November 11, 2008 4:09 AM
 

CoreyRoth said:

I am afraid I don't have any experience calling a web service from BuddyScript.  Calling the MOSS web service is just like calling any other web service when passing credentials.  I would look and see if there is a way to pass the credentials when calling a web service.  You can't pass them in via the XML string though.

November 11, 2008 1:36 PM
 

Sharepoint Web Servisleri - Search/Query Web Servisi | YAZILIM KUL??B?? said:

Pingback from  Sharepoint Web Servisleri - Search/Query Web Servisi | YAZILIM KUL??B??

May 6, 2009 1:29 AM
 

Ian P said:

How would you specify specific doc types from the query?  E.g:

<QueryText language='en-US' type='STRING'>sharepoint filetype:'pdf'</QueryText>

This does not work!

July 20, 2010 4:17 AM
 

CoreyRoth said:

@Ian Enterprise Search does not like single quotes.  Replace with a quote (") and you should be good.  Since you're dealing with a string you will probably have to use \" to delimit it properly.

July 20, 2010 9:24 AM
 

Stefam said:

Hello  i use SP Foundation 2010.

I have a problem with the search Webservice.

I become no results with this sourcecode

Where is the error?

Can you help me?

thx!

Suche123.QueryService test = new Suche123.QueryService();

           test.Credentials = CredentialCache.DefaultCredentials.GetCredential(new Uri(test.Url), "NTLM");

           test.PreAuthenticate = true;

if (!test.Status().Equals("ONLINE")) {

return;

}

               StringBuilder queryXml = new StringBuilder();

               queryXml.Append("<QueryPacket xmlns=\"urn:Microsoft.Search.Query\" Revision=\"1000\">");

               queryXml.Append("<Query domain=\"QDomain\">");

               queryXml.Append("<SupportedFormats>");

               queryXml.Append("<Format>");

               queryXml.Append("urn:Microsoft.Search.Response.Document.Document");

               queryXml.Append("</Format>");

               queryXml.Append("</SupportedFormats>");

               queryXml.Append("<Range>");

               queryXml.Append("<Count>50</Count>");

               queryXml.Append("</Range>");

               queryXml.Append("<Context>");

               queryXml.Append("<QueryText language=\"en-US\" type=\"STRING\">");

               queryXml.Append("");

               queryXml.Append("</QueryText>");

               queryXml.Append("</Context>");

               queryXml.Append("</Query>");

               queryXml.Append("</QueryPacket>");        

           string resultXml2 = "";

           var queryResults = new System.Data.DataSet();

            resultXml2 = test.Query(queryXml.ToString());

            queryResults = test.QueryEx(queryXml.ToString());

            DataGrid1.DataSource = queryResults.Tables[0];

           DataGrid1.DataBind();

July 30, 2010 4:35 AM
 

java script code for writing api for microsoft serach | ?????? said:

Pingback from  java script code for writing api for microsoft serach | ??????

December 20, 2010 3:52 AM
 

IT Ramblings said:

How to: Query Search using the Web Service

March 22, 2011 10:39 AM
 

SharePoint 2010 Enterprise Search KeywordQuery Class, KeywordQuery Class said:

Pingback from  SharePoint 2010 Enterprise Search KeywordQuery Class, KeywordQuery Class

March 23, 2011 4:14 AM
 

Eric Xue said:

@Stefam, have you tried to switch to "Kerberos" for the authentication provider rather than "NTLM" on SharePoint 2010 Foundation server?

It might work for you.

All best

Eric

April 13, 2011 11:17 PM
 

Cameron said:

I am attempting to get the RecordClick to work. I am attempting to use the search from a non-sharepoint site using the available web services and there is no documentation out there on how to make this work. Without RecordClick all sorts of functionality is broken.

Thanks

-Cam

April 27, 2011 10:48 AM
 

Kanja Saha said:

Hi Corey,

Thanks much for the post. However whenever I try to filter on Write column for a specific datetime, the time value is ignored.  So the query below will return all documents with Write > ''2011-03-11 00:00:00' NOT

'2011-03-11 11:07:24'.

Please let me know if there is any way to address this issue.

thanks

Kanja

<Context>

     <QueryText language="en-US" type="MSSQLFT">SELECT Title, Path, Description, Write, Rank, Size FROM Scope() WHERE CONTAINS('Accounting') AND "Scope" = 'Corporate Documents' and  "Write" > '2011-03-11 11:07:24'</QueryText>

   </Context>

May 12, 2011 9:45 PM
 

sudheer said:

Hi!

Thanks for such a nicepost.

But how can i pre query suggestions and post query suggestions using this query webservice.

Trying to figure it out since soem days....Please help me ASAP..

Thanks in advance!

Regards,

Sudheer

July 19, 2011 6:33 AM
 

CoreyRoth said:

@sudheer You can use jQuery to call the web service as users type in their search terms.  There are a few solutions out there already with "search as you type" implementations.

July 20, 2011 9:03 AM
 

Gosia said:

Hi.

I try to use ROW_NUMBER() function inside my MSSQLFT query and I getting error: "ERROR_BAD_QUERY Your query is malformed. Please rephrase your query.". Here is my code:

'<QueryText type="MSSQLFT" language="en-US">'

                   + 'SELECT ROW_NUMBER() OVER(ORDER BY Write DESC) AS ro, '

                   + 'Title, Path, Description, Write, Rank, Size, Author, SiteName,

                   + 'FROM Scope() '

                   + '</QueryText>'

I'm calling ws from jQuery. If I remove Row_number part everything is working ok.

Is anyone know why this isn't working?

September 15, 2011 5:06 AM
 

CoreyRoth said:

@Gosia ROW_NUMBER() is a T-SQL statement.  It does not exist in the Full Text SQL Query language to my knowledge.

September 15, 2011 5:33 PM
 

Asif said:

Article is very helpful. Thank you.

Was wondering if I can restrict querying to a particular Content Source given that I have multiple content sources.

Also when fast crawls my site can I detect the crawler perhaps by looking into the Request headers?

December 29, 2011 2:08 PM
 

CoreyRoth said:

@Asif yes, you can restrict queries by content source, by using the ContentSource keyword.

www.dotnetmafia.com/.../some-handy-keywords-you-might-find-useful-in-sharepoint-enterprise-search.aspx

Are you saying you are going to put some code in your site to look for a FAST crawl?  I imagine you could identify it by looking at the identify of the user crawling (i.e.: your default content access account).

January 5, 2012 3:45 PM
 

Gig said:

ANy idea on how retrieve the number of replies in the discussion board?

I am able to search in the topic, but not to get the replies.

Thanks.

January 23, 2012 2:34 AM
 

Working with SharePoint Foundation Search API « DotNetAdil said:

Pingback from  Working with SharePoint Foundation Search API &laquo; DotNetAdil

February 3, 2012 4:48 AM
 

CoreyRoth said:

@Gig I don't believe search picks up that information (but I could be wrong).  You would probably have to write some code to look it up for each result.

February 7, 2012 12:04 AM
 

Working with SharePoint Foundation Search API « DotNetAdil said:

Pingback from  Working with SharePoint Foundation Search API &laquo; DotNetAdil

February 20, 2012 4:18 AM
 

sanju said:

Thanks for the great post. I was wondering if you could tell me how do i get the contents of the matched dcouments. For e.x., using the search api, if i search for something, which is either tagged using enterprise keyword or some content inside the document, I should get the title and first matching line that contains the searched item. i.e. , I upload a doc called Sales.docx, with a title "Sales". It has a sentence like , "This year our revenue was $900 million ....". I upload it with a tag like "company revenue". When I search for revenue, I should get the title, "Sales" and matching sentence , ".Our revenue was $900 mill....". In my case, I upload this to shared docs folder and have created a managed property to ows_Name(Text), ows_Description(Text) and I cannot get these two fields. I can get only the filename sales.docx.

April 27, 2012 2:28 AM
 

Saurabh said:

Hi

I am trying to offer scope specific query suggestions using the SearchBoxEx webpart. I want to determine where the queryXml is being generated which is sent to the search.asmx service to retrieve query suggestions.

I have created my own WCF for accomplishing this.

But I am facing an issue: How to pass the selected scope in dropdown to the WCF so that query suggestions are scope specific?

Kindly help me out.

Regards

May 21, 2012 4:50 AM
 

John said:

Hi CoreyRoth

I am trying to set number of characters in the Description part of the result that we get through this Query packet. Is it possible.?

Kindly let me know on this..

Thanks in advance..

December 17, 2012 10:57 AM
 

carboncopy said:

Hi Corey,

I'm running a full-text query against the People scope, but it seems it does not search in all given lookup field. For instance while I get items which have the word I was looking for in company or address field but none of them which have the word in the preferredname field - despite this is in the list of fields of the select query.

Preferredname is indexed and I can find people by name through the OOB people finder.

This worked great in MOSS 2007 but since I'm migrated to SP2010 it doesn't work properly.

What could be wrong here?

February 14, 2013 4:51 AM
 

CoreyRoth said:

First, you want to stop using Full Text SQL Queries since they are gone in SharePoint 2013.  Try it with a keyword query and see if you get the same results.

April 11, 2013 10:25 PM
 

CoreyRoth said:

@Amit Change this line to <QueryText language="en-US" type="STRING">Accounting Scope:"Corporate Documents"</QueryText>

July 16, 2013 11:05 AM
 

Sam said:

Hi Corey,

I see the original blog is a few years old now but yet it still being posted, and replied, to which is awesome.  

I am hoping you can shed some light on a particular problem I am experiencing.  The full extent of the issue is described on the URL above.  In short though I am using query packet and returning results sorted by "Write" DESC.  If the page size - i.e. the count - is 20 I get 'bad' results, in that the results are all missorted.  In April 2013 I changed the count to be 40 and all was well until this month.  The issue reoccured.  Setting the count to 45 this time again corrected the problem.  But I just can't figure out why this would happen.

I've been using Mossman's tool and entered by querypacket and can reproduce the issue.  Have I really unearthed a Sharepoint 2010 bug or am I still doing something wrong?

Any help or advice would be much appreciated!

Thanks,

Sam

BTW, I've worked with a number of great Infusion guys in the past.

August 15, 2013 3:19 PM
 

CoreyRoth said:

@Sam that's odd.  I am guessing it has something to do with the fact that there are more documents coming back in the results now.  Sorting has always been a bit unreliable in 2010 in this manner and that may just be the case of what it is.  On the plus side, it gets better in 2013.

October 11, 2013 10:48 AM
 

CoreyRoth said:

@Mohamed this is because SQL Syntax was removed from SharePoint 2013.  You will need to convert your query to a KQL query in order for it to work.  I also recommend updating your code to use the REST or JavaScript CSOM interfaces as well.  The web service interface is deprecated.

November 4, 2013 4:14 PM
 

Maggie said:

Hi,

 I will be implementing a web application that will be utilizing sharepoint search service. My company has never used it but i intend to start my questions to the admin by finding out what the crawl schedule was, and the stop words set up if any. Need to know about stop words as part of the search application being created. Are there any other things, question wise, i need to be asking the admin besides security setup? This is my first experience with SharePoint. Any assistance would help

June 11, 2014 7:48 PM
 

CoreyRoth said:

@maggie the crawl schedule is configurable on your server to meet your needs.  I'm not sure what you mean by stop words.

July 1, 2014 9:21 AM
 

Search does not returning list item | sharepoint2013admin said:

Pingback from  Search does not returning list item | sharepoint2013admin

July 18, 2014 5:51 AM

Leave a Comment

(required)  
(optional)
(required)  
Add

About CoreyRoth

Corey Roth is an independent SharePoint consultant specializing in ECM, Apps, and Search.
2012 dotnetmafia.
Powered by Community Server (Non-Commercial Edition), by Telligent Systems