-1

I have a pagetypefilter in my search function and have a scenario where page b inherits from page a. When I check the page a option in my filterlist I still get hits which type is page b. Is it possible to only search for basetypes in EPiServer search?

Page b in my case:

 public class b : a
    {
        public virtual string ExternalUrl { get; set; }
    [ScaffoldColumn(false)]
    [JsonIgnore]
    [Searchable(false)]
    public virtual string Id { get; set; }
}

and page a

  public class a: SitePageData
{
    [Display(GroupName = SystemTabNames.Content, Order = 4)]
    [CultureSpecific]
    [UIHint(UIHint.Textarea)]
    public virtual String Intro { get; set; }

    [Display(GroupName = SystemTabNames.Content, Order = 5)]
    [CultureSpecific]
    public virtual XhtmlString MainBody { get; set; }

    [Display(GroupName = SystemTabNames.Content, Order = 6)]
    public virtual ContentArea MainContentArea { get; set; }

    [Display(GroupName = SystemTabNames.Content, Order = 8)]
    public virtual RelatedInformationBlock RelatedInformation { get; set; }

    [Display(GroupName = SystemTabNames.Settings, Order = 9000)]
    public virtual SocialMediaShareLinksBlock ShareLinks { get; set; }

    public override void SetDefaultValues(ContentType contentType)
    {
        base.SetDefaultValues(contentType);

        ShareLinks.ShowFacebookShareLink = true;
        ShareLinks.ShowTwitterShareLink = true;
        ShareLinks.ShowLinkedInShareLink = true;
    }
}

And in my pagetypefilter I have only checked the option for class a

Here's the complete query

        private IQueryExpression CreateQuery(SearchQuery searchQuery)
    {
        var query = new GroupQuery(LuceneOperator.AND);

        if (!(searchQuery.SearchText.StartsWith("\"") && searchQuery.SearchText.EndsWith("\"")))
            searchQuery.SearchText = searchQuery.SearchText.Replace(" ", "* ") + "*";

        if (!string.IsNullOrWhiteSpace(searchQuery.SearchText))
        {
            var searchTextQuery = new GroupQuery(LuceneOperator.OR);
            //searchTextQuery.QueryExpressions.Add(new TermBoostQuery(searchQuery.SearchText, Field.Created,10000F));
            searchTextQuery.QueryExpressions.Add(new TermBoostQuery(searchQuery.SearchText, Field.Title, 1F));
            searchTextQuery.QueryExpressions.Add(new TermBoostQuery(searchQuery.SearchText, Field.ItemType, 0.2F));

            searchTextQuery.QueryExpressions.Add(new TermBoostQuery(searchQuery.SearchText, Field.DisplayText, 0.1F));


            searchTextQuery.QueryExpressions.Add(new FieldQuery(searchQuery.SearchText));
            query.QueryExpressions.Add(searchTextQuery);
        }

        var virtualPathQueryGroup = new GroupQuery(LuceneOperator.OR);

        if (searchQuery.RootsFilter.IsNullOrEmpty())
        {
            var contentRootQuery = new VirtualPathQuery();
            contentRootQuery.AddContentNodes(ContentReference.StartPage);
            virtualPathQueryGroup.QueryExpressions.Add(contentRootQuery);

            var contentRootQuery2 = new VirtualPathQuery();
            contentRootQuery2.AddContentNodes(SiteDefinition.Current.GlobalAssetsRoot);
            virtualPathQueryGroup.QueryExpressions.Add(contentRootQuery2);
            var contentRootQuery3 = new VirtualPathQuery();
            contentRootQuery3.AddContentNodes(SiteDefinition.Current.ContentAssetsRoot);
            virtualPathQueryGroup.QueryExpressions.Add(contentRootQuery3);
        }
        else
        {
            virtualPathQueryGroup.QueryExpressions.Clear();

            foreach (var root in searchQuery.RootsFilter)
            {
                var contentRootQuery = new VirtualPathQuery();
                contentRootQuery.AddContentNodes(root);
                virtualPathQueryGroup.QueryExpressions.Add(contentRootQuery);
            }
        }

        query.QueryExpressions.Add(virtualPathQueryGroup);

        if (searchQuery.PageTypesFilter.Any() || searchQuery.MediaTypesFilter.Any())
        {
            var contentQuery = new GroupQuery(LuceneOperator.OR);

            if (searchQuery.MediaTypesFilter.Any())
            {
                var mediaContentQuery = new GroupQuery(LuceneOperator.OR);

                foreach (var type in searchQuery.MediaTypesFilter)
                    mediaContentQuery.QueryExpressions.Add(new TypeContentQuery(type));

                contentQuery.QueryExpressions.Add(mediaContentQuery);
            }

            if (searchQuery.PageTypesFilter.Any())
            {
                var pageContentQuery = new GroupQuery(LuceneOperator.AND);
                var pageContentQueryTypes = new GroupQuery(LuceneOperator.OR);

                foreach (var type in searchQuery.PageTypesFilter)
                    pageContentQueryTypes.QueryExpressions.Add(new TypeContentQuery(type));

                pageContentQuery.QueryExpressions.Add(new FieldQuery(CultureInfo.CurrentUICulture.Name, Field.Culture));
                pageContentQuery.QueryExpressions.Add(pageContentQueryTypes);

                contentQuery.QueryExpressions.Add(pageContentQuery);
            }

            query.QueryExpressions.Add(contentQuery);
        }

        if (!searchQuery.CategoriesFilter.IsNullOrEmpty())
        {
            var categoriesToCommaList = String.Join(",", searchQuery.CategoriesFilter);
            var categoryQuery = new ContentCategoryQuery(CategoryList.Parse(categoriesToCommaList), LuceneOperator.OR);

            query.QueryExpressions.Add(categoryQuery);
        }
        //    // The access control list query will remove any files the user doesn't have read access to
        AccessControlListQuery aclQuery = new AccessControlListQuery();
        aclQuery.AddAclForUser(PrincipalInfo.Current, HttpContext.Current);
        query.QueryExpressions.Add(aclQuery);


        return query;
    }

And lastly the Typequery itself:

 public class TypeContentQuery : IQueryExpression
{
    private readonly Type contentType;
public TypeContentQuery(Type contentType)
{
    if (contentType == null)
    {
        throw new ArgumentNullException("contentType");
    }
    this.contentType = contentType;
}

public string GetQueryExpression()
{
    var typeExpression = "\"" + ContentSearchHandler.GetItemTypeSection(contentType) + "\"";
    return new FieldQuery(typeExpression, Field.ItemType).GetQueryExpression();
    }
}
dont_trust_me
  • 540
  • 8
  • 24
  • Does this mean you want to exclude all derived classes, in your case `class b` should not be listed in your results at all? We would also need to se how you construct your a, b objects. – Eric Herlitz Dec 08 '16 at 12:25
  • Exactly. edited my question – dont_trust_me Dec 08 '16 at 13:35
  • Well, typically OOTB I'd say no. But you do have the `contentSearchHandler.GetContent(xxx);` and can work from that result to reflect the results. – Eric Herlitz Dec 11 '16 at 20:25

2 Answers2

0

Looks like the standard pagefilter isn't implemented to do this. But you should be able to create your own filters by extending the EPiServer.Filters.IPageFilter class. And in your fileter use the Type.IsSubclassOf to check the Types for the pages.

Asthiss
  • 221
  • 2
  • 8
0

The problem I believe is the indexing. In the class ContentSearchHandler the method GetItemType(Type contentType) adds all the base types to the ItemType field. Since the method is public virtual you should be able to replace it with your own implementation in the StructureMap container which only returns the base type.

Andreas
  • 1,355
  • 9
  • 15