How to perform search for multiple terms in Sitecore 7 ContentSearch API?
Asked Answered
S

3

6

I am exploring the new Sitecore.ContentSearch "LINQ to Sitecore" API in Sitecore 7. It is my understanding that Sitecore recommends using the new LINQ API over the existing Sitecore.Search API, however, I am struggling to perform even the simplest of queries.

Take for instance the following search query: "hello world".

Using the Sitecore.Search API, the terms "hello world" would typically be passed through a QueryParser which would result in documents matching the word "hello" OR "world". Documents containing both terms would be scored higher that those with just one.

How does one perform this same query using LINQ?

Here's what I have tried:

var results = SearchContext.GetQueryable<MyResultItem>();

var terms = searchTerm.Split(' ');

// Not supported exception
results = results.Where(r => terms.Any(t => r.Content.Contains(r)));

// Close, but performs an "AND" between terms, and does not appear
// to score documents properly
foreach (var term in terms)
{
    results = results.Where(r => r.Content.Contains(t));
}

UPDATE

I am convinced that I am missing something really simple. Surely with all the work that went into the new search API, this simple use case wasn't overlooked... right?

As a workaround, I tried opening the default sitecore_web_index using the existing SearchManager, however, this does not work.

Unfortunately, I have had to resort to the existing API until I can figure this out. I will be sure to update this question with my findings.

UPDATE 2

I found the Sitecore.ContentSearch.Utilities.LinqHelper class which partially solves the problem. You can use it to dynamically build a query similar to a BooleanQuery in Lucene.Net, however, it's options are limited and it adds a bit of performance overhead.

Seafowl answered 23/6, 2013 at 3:9 Comment(2)
This blog article might help sitecore.net/Community/Technical-Blogs/Getting-to-Know-Sitecore/…Colossian
@Colossian Thanks for the link! The LinqScratchPad tool will definitely come in handy. That said, I still cannot find an example of an 'OR' style query or one that utilizes any sort of query parsing. They only show how to match based on simple criteria, such as _templatename == "X". While that's useful, I am simply trying to implement a run-of-the-mill site search at this point.Seafowl
S
22

All of the predicate builders I tried didn't work, however, Sitecore 7 ships with a PredicateBuilder of it's own that did the trick.

using Sitecore.ContentSearch;
using Sitecore.ContentSearch.Linq;
using Sitecore.ContentSearch.SearchTypes;
using Sitecore.ContentSearch.Utilities;
// Sitecore 7 (Update 1+): using Sitecore.ContentSearch.Linq.Utilities;

...

var index = ContentSearchManager.GetIndex("sitecore_web_index");
using (var context = index.CreateSearchContext())
{
    var predicate = PredicateBuilder.True<SearchResultItem>();
    foreach (var t in term.Split(' '))
    {
        var tempTerm = t;
        predicate = predicate.Or(p => p.Content.Contains(tempTerm));
    }

    var results = context.GetQueryable<SearchResultItem>().Where(predicate).GetResults();

    ...
}
Seafowl answered 10/7, 2013 at 21:6 Comment(4)
Derek, did you do this with Solr or just Lucene? I get errors when I try to use the predicate.Or with Solr.Reorder
I have only used this with Lucene.Seafowl
Really nice work, Derek. You exposed the powerful PredicateBuilder to me for uses that extend far beyond Sitecore.ContentSearch. Thanks :)Kick
Getting error on .GetResults() method, System.Linq.IQueryable<Sitecore.ContentSearch.SearchTypes.SearchResultItem>' does not contain a definition for 'GetResults' and no extension method 'GetResults' accepting a first argument of typeSheeree
T
1

I think this is related to linq not to sitecore.

I don't test this but have a look at this article http://www.albahari.com/nutshell/predicatebuilder.aspx

You can also look at this documentation http://sdn.sitecore.net/upload/sitecore7/70/developer's_guide_to_item_buckets_and%20search_sc7-a4.pdf

Talavera answered 9/7, 2013 at 7:48 Comment(2)
Thanks very much. Page 50 of the second link answered all my questions!Seafowl
Unfortunately, the PredicateBuilder from the first link throws an exception: Unsupported expression node type: LambdaSeafowl
W
0

I was able to use PredicateBuilder with Solr and implement queries including the OR operator. See http://www.nttdatasitecore.com/en/Blog/2013/November/Building-Facet-Queries-with-PredicateBuilder.aspx

Wordsworth answered 6/11, 2013 at 23:18 Comment(1)
While this link may answer the question, you should avoid link-only answers but summarize or quote the article, because links tend to decay over time.Wirework

© 2022 - 2024 — McMap. All rights reserved.