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>
7
  • Not sure if this is still a thing, but did you try normalizing your guid? Sitecore.ContentSearch.Utilities.IdHelper.NormalizeGuid(currentArticle._Id)
    – Mark Cassidy
    Commented May 2, 2018 at 15:02
  • Can you check the query in your search log?
    – Gatogordo
    Commented May 2, 2018 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 +*:*) Commented May 2, 2018 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. Commented May 2, 2018 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. Commented May 3, 2018 at 7:48

1 Answer 1

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.

5
  • 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.) Commented May 7, 2018 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. Commented May 8, 2018 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. Commented May 8, 2018 at 15:20
  • Yes, but the field "_group.guid" doesn't exist :) Commented May 8, 2018 at 18:54
  • Ahhh, gotcha. That... well, I'm not convinced that makes sense, but at least I understand it. Thanks! Commented May 9, 2018 at 12:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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