Sitecore7 LinqHelper.CreateQuery Buggy?

2019-06-10 04:01发布

问题:

This is more of a clarification type question rather than actual problem regarding LinqHelper.CreateQuery method.

So,
This method has 3 overloads. The 2 in question here, are: 1.LinqHelper.CreateQuery<SearchResultItem>(searchContext, searchStringModel) 2.LinqHelper.CreateQuery<SearchResultItem>(searchContext, searchStringModel, startLocationItem) [I haven't used any additional context here so used the default null]

Now,
In order to search for items with in a specific location of the content tree ( for example under a particular folder you have 1000 items) I can use method 1 using the query:

query = "location:{FOLDER_GUID};+custom:my_filed_name|bla_bla"

Which works perfectly. But (from what I understood from the method signature is that) I should also be able to use method 2 like the following:

SitecoreIndexableItem folderID = SitecoreIndexableItem)contextDatabase.GetItem({FOLDER_GUID});
var index = ContentSearchManager.GetIndex(new SitecoreIndexableItem(Sitecore.Context.Item));
using (var context = index.CreateSearchContext())
{
    List<SearchStringModel> searchStringModel = new List<SearchStringModel>();
    searchStringModel.Add(new SearchStringModel("my_field_name", "bla_bla"));
    List<Sitecore.Data.Items.Item> resultItems = LinqHelper.CreateQuery(context, searchStringModel, folderID).Select(toItem => toItem.GetItem()).ToList();                
}

Problem is for the above method (method 2) the searching works fine, what doesn't work is the "startLocationItem" (folderID in this case).

FOR EXAMPLE,
IF in my entire sitecore tree has total 3 items containing "my_filed_name=bla_bla"
BUT, only 1 item contains "my_filed_name=bla_bla" in the Folder ({FOLDER_GUID}, "the perticular folder" in this case)
THEN,
Method 1 returns 1 item (WHICH IS CORRECT) BUT, Method 2 returns 3 items, despite "startLocationItem = {FOLDER_GUID} ... (WHICH I DONT THINK IS CORRECT)

Question is :
1. What is the exact purpose of "startLocationItem" in Method 1 ?
2. And what's the benefit of using "location" filter or "startLocationItem for method 2" ?

回答1:

LinqHelper is an internal helper class and should not be used in normal operation. It is to help the Sitecore UI talk to the search back-end. Its syntax could be changed at any time so could potentially break things based on it and it is also not documented.

You would be better to convert your query into a normal Linq query ie

using (var context = index.CreateSearchContext)
{
    context.GetQueryable<SearchResultItem>().Where(x =>x.Paths.Contains(ID.Parse("your GUID Here")))
}

The 'location' in the LinqHelper string is equivalent to the Paths (or _path) field stored in the index.

This field contains a list of all the parent items of an item, held as a list of GUIDs.

By filtering by _path you restrict the query to a certain node of the tree without effecting the score, for example:

/home (id:1234) 
   /animals (id:5678 = path:1234 / 5678
       /cats (id:1111) = path: 1234 / 5678 / 1111
       /dogs (id:2222) = path: 1234 / 5678 / 2222 
   /cars (id:4567) = path: 1234 / 4567
       /sports (id:3333) = path: 1234 / 4567 / 3333

If you filter on animals (ie 5678) you restrict the search only that item and its children.

Using a filter means you can restrict the context of a search without that part effecting the scoring of the main query, so you would end up with:

using (var context = index.CreateSearchContext)
{
    context.GetQueryable<SearchResultItem>().Where(x =>Name.Contains("Exciting"))
           .Filter(y => y.Paths.Contains(ID.Parse("your GUID Here")
}

This would search only inside the part of the tree you have filtered by for where name contains 'exciting'.

Hope that helps :)