Gravatar for debabrata.biswas@nttdata.com

Question by debubiswas, May 9, 2014 2:53 AM

How do I replace usage of earlier "Coveo.CES.Web.Search.WebService.SearchService" in code to perform queries

How do I replace usage of earlier "Coveo.CES.Web.Search.WebService.SearchService" in code to perform queries now on "coveo for sitecore". I was asked to use REST or LINQ but really need some examples. This is really needed for me to be used from within my sitecore pages code behind as I used to before.

3 Replies
Gravatar for dan@getfishtank.ca

Answer by Dan Cruickshank, May 9, 2014 12:02 PM

Sorry to post this as an answer but I can't format this properly in the comments.

This doesn't exactly answer your LINQ query question but hopefully it can start you don't the right path:

                var templateIds = new List<ID> {new ID("guid"), new ID("guid")};
                var contentSearchResults =
                context.GetQueryable<SearchResultItem>().Where(
                        i =>
                            templateIds.Contains(i.TemplateId) &&
                            DateUtil.IsoDateToDateTime(i["DateTimeFieldInSitecore"]) > DateTime.Now).ToList();

I would still look into the ContentSearch API to do some proper field-to-variable mapping. It would save you from having to use statements like DateUtil.IsoDateToDateTime(i["DateTimeFieldInSitecore"]).

Gravatar for debabrata.biswas@nttdata.com

Comment by debubiswas, May 9, 2014 12:09 PM

Thanks Dan. Appreciate your help. Actually I have defined these "computed coveo fields" (https://developers.coveo.com/display/public/SC201404/Creating+Computed+Fields) in "coveo.searchprovider.config" that are similar to ones you see above like "@Templateid", "@lasttime" etc. that are not one-to-one mapped with sitecore fields. So in other words I need to make a query or it's equivalent in LINQ to use these computed fields. How do I do that using LINQ?

Gravatar for dan@getfishtank.ca

Comment by Dan Cruickshank, May 9, 2014 12:37 PM

Apologies on the formatting. The easiest way to access the field is:

context.GetQueryable<SearchResultItem>().Where(
                        i =>
                            i["nameOfComputedField"] == "text"))

My prefered way would have you creating a simple class like:

public class CustomResultItem : SearchResultItem {
  [IndexField("_nameOfComputedField")]
  public string CustomField { get;set;}  
}

then your query would change to:

context.GetQueryable<CustomResultItem>().Where(
                        i =>
                            i.CustomField == "text"))
Gravatar for debabrata.biswas@nttdata.com

Comment by debubiswas, May 9, 2014 12:47 PM

Your first example I think won't work because in i["nameOfComputedField"] "i" is equivalent to Sitecore Item and it won't know about "nameOfComputedField". Right?

About your example of CustomResultItem class, is "_nameOfComputedField" the same name as "fieldName" defined for the in the config file? Let me know as I can then try this. Also what is the namespace for "IndexField"? Thanks again Dan.

Gravatar for dan@getfishtank.ca

Comment by Dan Cruickshank, May 9, 2014 12:50 PM

The first sample will work. i is not the sitecore item. i is the SearchResultItem which is provided by the Search Index, not Sitecore per se.

And sorry for any confusion about having the "_" prefix in one sample and not the other. I always mean to prefix my computed fields with an underscore.

Gravatar for dan@getfishtank.ca

Comment by Dan Cruickshank, May 9, 2014 12:52 PM

yes "_nameOfComputedField" is the same as the "fieldName"

Gravatar for debabrata.biswas@nttdata.com

Comment by debubiswas, May 9, 2014 1:01 PM

cool. trying it now. Also what is the namespace for "IndexField" that you used as a custom attribute?

Gravatar for dan@getfishtank.ca

Comment by Dan Cruickshank, May 9, 2014 1:02 PM

No problem. Namespace: Sitecore.ContentSearch.IndexFieldAttribute

Gravatar for mlaporte@coveo.com

Answer by Martin Laporte, May 9, 2014 3:44 AM

If you need to execute queries from codebehind in a Sitecore context I'm guessing the Linq search provider is the way to go. This page contains information about how to do so, and there is even a code sample in the comments. I can't provide much more info myself as I don't know much about Sitecore, but certainly others will be able to help later on today, when it's morning in Canada.

Otherwise, you always have the possibility to use the REST service to perform queries. Some info is available here but it's still somewhat incomplete (we're working on that). In a Sitecore context the Rest search API is available through /Coveo/Rest, so a request for /Coveo/Rest?q=something would search for "something" and return results as JSON. But to do that you'll need to authenticate using whatever means is set up in your Sitecore site --- probably not a good idea when already running inside codebehind. So the LINQ approach is probably better.

Gravatar for debabrata.biswas@nttdata.com

Comment by debubiswas, May 9, 2014 3:47 AM

Already looked at it but not sure how I can pass queries like following using LINQ. Sample provided there by Dan is just not good enough.

My sample query: (@Templateid=("7FD926AF-4AC7-4CE5-8180-4EBCD6263896","2613A567-692B-4488-9EF8-B38021E72003","B24B6FCA-1EF1-45E1-BB23-D17FDC87897D") AND (@lasttime>=today AND @lasttime<=today+48h) AND @hidefromticker==False

Gravatar for dan@getfishtank.ca

Comment by Dan Cruickshank, May 9, 2014 11:52 AM

Have you created a specific class for the content search to return or are you planning on using the default "SearchResultItem" from Sitecore?

When using LINQ you'll be using standard lambda expression and C# syntax to write your query. Coveo is actually abstracted from it. Some standard Sitecore docs on the ContentSearch API may help a lot.

Gravatar for amorin@coveo.com

Answer by Antoine Morin, May 9, 2014 2:20 PM

The information Dan provided is correct. If you want to perform queries from the code behind, Linq would probably be the best choice. Here's an example that contains a where clause on the template id and on a date field. You'll have to adapt the code to your situation. Also, as Dan mentionned, you can also look at Sitecore's ContentSearch API for more information.

var searchIndex = ContentSearchManager.GetIndex("sitecore_master_index");
using (var context = searchIndex.CreateSearchContext(SearchSecurityOptions.DisableSecurityCheck)) {
    var results = context.GetQueryable<SearchResultItem>()
                    .Where(item => item.TemplateId == new ID("{D0B70D73-C95B-4B8F-B7A6-EBA91CBC8301}") || item.TemplateId == new ID("{76036F5E-CBCE-46D1-AF0A-4143F9B557AA}"))
                    .Where(item => item.CreatedDate >= DateTime.Now.AddMonths(-1) && item.CreatedDate <= DateTime.Now.AddHours(48));

    string content = String.Format("Count: {0}<br />", results.Count());
    foreach (var result in results) {
        // Process the results here
    }
}

You can also access custom fields such as computed fields by using the SearchResultItem's accessor. Ex.:

.Where(item => item["HideFromTicker"] == false);

You might want to include the following namespaces for this code:

using Sitecore.ContentSearch;
using Sitecore.ContentSearch.SearchTypes;
using Sitecore.ContentSearch.Security;
using Sitecore.Data;

Using POCOs, e.g., classes that inherit from the SearchResultItem class could help you simplify your queries. Sitecore already has a lot of documentation regarding this subject (see http://www.sitecore.net/Community/Technical-Blogs/Sitecore-7-Development-Team/Posts/2013/06/Sitecore-7-POCO-Explained.aspx ).

Ask a question