4

I have a query that's supposed to return related articles to the current article that aren't the current article but are the same category. However, it keeps including the current article in the results. It uses this predicate:

var predNotCurrentItem = PredicateBuilder
    .True<BlogSearchResult>()
    .And(x => x.ItemId.Guid != currentArticle._Id);
var predPrimaryCategory = predNotCurrentItem.And(x => x.PrimaryCategory == currentArticle.PrimaryCategory._Id);

dest = _blogSearch.GetMostRecentArticles(predPrimaryCategory, count);

Which, by way of the GetMostRecentArticles function, calls this:

protected TList Search(Expression<Func<TSingle, bool>> predicate = null)
{
    TList results;

    using (IProviderSearchContext context = SearchIndex.CreateSearchContext())
    {
        IQueryable<TSingle> query;
        if (predicate != null)
        {
            query = context.GetQueryable<TSingle>().Filter(predicate);
        }
        else
        {
            query = context.GetQueryable<TSingle>();
        }
        results = new TList { Results = query.Where(x => !x.ExcludeFromSearch).ToList().Distinct() };
    }

    return results;
}

I've confirmed that x.ItemId.Guid and currentArticle._Id are returning the correct values, and they're both GUIDs so the comparison should work correctly. I've confirmed that it gets to the Filter() call as expected.

What am I doing wrong that prevents it from filtering out the article with matching GUID as expected?

(Note: I suspect this is a C# thing rather than a Sitecore thing specifically, but if it matters we're using Sitecore 8.1u3 with Lucene 3.0.3.)

edit 1: adding configuration

Relevant portion of the search configuration:

<fieldMap type="Sitecore.ContentSearch.FieldMap, Sitecore.ContentSearch">
    <fieldNames hint="raw:AddFieldByFieldName">
        <field fieldName="Article Title" storageType="YES" indexType="TOKENIZED" vectorType="NO" boost="1f" type="System.String" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider" />
        <field fieldName="Author" storageType="YES" indexType="UNTOKENIZED" vectorType="NO" boost="1f" type="System.Guid" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider" />
        <field fieldName="Primary Category" storageType="YES" indexType="UNTOKENIZED" vectorType="NO" boost="1f" type="System.Guid" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider" />
        <field fieldName="Additional Categories" storageType="YES" indexType="TOKENIZED" vectorType="NO" boost="1f" type="System.String" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider" />
        <field fieldName="States" storageType="YES" indexType="TOKENIZED" vectorType="NO" boost="1f" type="System.String" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration.Sitecore.ContentSearch.LuceneProvider" />
        <field fieldName="Publish Date" storageType="YES" indexType="UNTOKENIZED" vectorType="NO" type="System.DateTime" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider" />
        <field fieldName="Keywords" storageType="YES" indexType="TOKENIZED" vectorType="NO" boost="1f" type="System.String" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider" />
        <field fieldName="Include on Blog Homepage" storageType="YES" indexType="UNTOKENIZED" vectorType="NO" boost="1f" type="System.Boolean" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider" />
        <field fieldName="Include in RSS Feeds" storageType="YES" indexType="UNTOKENIZED" vectorType="NO" boost="1f" type="System.Boolean" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider" />
        <field fieldName="Exclude from Related Blog Posts" storageType="YES" indexType="UNTOKENIZED" vectorType="NO" boost="1f" type="System.Boolean" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider" />
    </fieldNames>
</fieldMap>
<documentOptions type="Sitecore.ContentSearch.LuceneProvider.LuceneDocumentBuilderOptions, Sitecore.ContentSearch.LuceneProvider">
    <indexAllFields>false</indexAllFields>
    <include hint="list:AddIncludedTemplate">
        <BlogArticle>(guid omitted)</BlogArticle>
    </include>
    <fields hint="raw:AddComputedIndexField">
        <field fieldName="_content" type="MyCompany.Library.Services.Search.Fields.RenderingContentsField, MyCompany.Library" />
    </fields>
    <include hint="list:AddIncludedField">
        <Keywords>(guid omitted)</Keywords>
        <ArticleTitle>(guid omitted)</ArticleTitle>
        <Author>(guid omitted)</Author>
        <PrimaryCategory>(guid omitted)</PrimaryCategory>
        <AdditionalCategories>(guid omitted)</AdditionalCategories>
        <States>(guid omitted)</States>
        <PublishDate>(guid omitted)</PublishDate>
        <IncludeOnBlogHomepage>(guid omitted)</IncludeOnBlogHomepage>
        <IncludeInRssFeeds>(guid omitted)</IncludeInRssFeeds>
        <ExcludeFromRelatedBlogPosts>(guid omitted)</ExcludeFromRelatedBlogPosts>
    </include>
</documentOptions>
  • Not sure if this is still a thing, but did you try normalizing your guid? Sitecore.ContentSearch.Utilities.IdHelper.NormalizeGuid(currentArticle._Id) – Mark Cassidy May 2 '18 at 15:02
  • Can you check the query in your search log? – Gatogordo May 2 '18 at 15:29
  • @MarkCassidy Doesn't seem like it should matter, but I'll give it a try. @Gatogordo It looks like this in the log: 815912 13:38:30 INFO ExecuteQueryAgainstLucene (custom_blog): +(-exclude_from_search:1 +*:*) - Filter : +(-exclude_from_related_blog_posts:1 +*:*) +(-_group:168a759392f24d099cdc5499256e97e8 +*:*) – Michael Smith May 2 '18 at 17:42
  • It looks like that Normalize function is only for string (presumably so they can be converted cleanly to GUIDs), but these are actual Guid objects populated out of Glass. – Michael Smith May 2 '18 at 17:47
  • The log you posted looks correct, at least if you are using the default index configuration. Are you using the default configuration? If not, could you show your index configuration? I'm mostly interested in which fields are included and their names. – Søren Kruse May 3 '18 at 7:48
2

From your search log and index configuration I think there's one or two things causing the issue.

x => x.ItemId.Guid != currentArticle._Id

Your expression above is being parsed incorrectly (well, incorrectly for what you want). It should instead be like this:

x => x.ItemId != Sitecore.Data.ID.Parse(currentArticle._Id)

You might need to store the current article ID in a variable outside the expression for it to work:

var currentArticleId = Sitecore.Data.ID.Parse(currentArticle._Id);
var filter = PredicateBuilder
                 .True<BlogSearchResult>()
                 .And(x => x.ItemId != currentArticleId);

If it is still not working you probably need to add the field for the item ID (_group) to your index configuration:

<field fieldName="_group" storageType="YES" indexType="TOKENIZED" vectorType="NO" boost="1f" type="System.GUID" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider">
    <analyzer type="Sitecore.ContentSearch.LuceneProvider.Analyzers.LowerCaseKeywordAnalyzer, Sitecore.ContentSearch.LuceneProvider" />
</field>

Comments

The line where you filter for ExcludeFromSearch:

results = new TList { Results = query.Where(x => !x.ExcludeFromSearch).ToList().Distinct() };

It would probably be more correct (and a tiny bit more performant) to use .Filter() instead of .Where(). Filters does not score the results and can be cached by Lucene.

The .Distinct() seem to be pointless from what I can see - every object in the list will be a separate object reference even though they might represent the same blog item.

| improve this answer | |
  • This appears to work! Thanks. Can you explain why, though? It doesn't seem like comparing them as GUIDs vs. comparing them as IDs should really make a difference. (Thank you also for the additional comments, which I'll take a look at.) – Michael Smith May 7 '18 at 13:05
  • 1
    Well, in short it's because the expression is not actually executed as such. Sitecore attempts to translate your C# expression into a Lucene query. From your log you can see that it translated x.ItemId.Guid into _group.guid - a field that doesn't exist in your index. – Søren Kruse May 8 '18 at 8:04
  • _group comes out of the default configuration, which I neglected to include because (a) I thought it was common to all Lucene indices, and (b) it's a bit on the large size. I should've mentioned that. Double-checked in Luke that it's included in the index and has values. – Michael Smith May 8 '18 at 15:20
  • Yes, but the field "_group.guid" doesn't exist :) – Søren Kruse May 8 '18 at 18:54
  • Ahhh, gotcha. That... well, I'm not convinced that makes sense, but at least I understand it. Thanks! – Michael Smith May 9 '18 at 12:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.