public static IQueryable <T> AddKeywordSearchQuery <T>(this IProviderSearchContext context, IQueryable <T> query, string searchTargetId, ICollection <string> keywords, KeywordSearchOptions options = null) where T : SearchResultItem { Assert.ArgumentNotNull(query, nameof(query)); Assert.ArgumentNotNull(context, nameof(context)); Assert.ArgumentNotNullOrEmpty(searchTargetId, nameof(searchTargetId)); Assert.ArgumentNotNull(keywords, nameof(keywords)); if (!keywords.Any()) { return(query); } var config = Factory.CreateObject("kotoha/configuration", true) as KeywordSearchConfiguration; var searchTarget = config.GetSearchTargetById(searchTargetId); if (searchTarget == null) { throw new InvalidOperationException($"Keyword search target was not found. (ID: {searchTargetId})"); } var contentField = context.Index.Configuration.DocumentOptions.ComputedIndexFields .OfType <KeywordSearchContentIndexField>() .FirstOrDefault(field => field.SearchTargetId == searchTargetId); if (contentField == null) { throw new InvalidOperationException($"Keyword search content field was not found. (ID: {searchTargetId})"); } var condition = options?.Condition ?? config.DefaultKeywordSearchOptions?.Condition ?? default; var searchType = options?.SearchType ?? config.DefaultKeywordSearchOptions?.SearchType ?? default; var generateFilterPred = CreatePredicateGenerator <T>(condition, searchType); var generateBoostPred = CreatePredicateGenerator <T>(condition, SearchType.Or); // Boost predicate must use OR operator // predicate for filtering var filterPred = keywords .Aggregate( PredicateBuilder.True <T>(), (acc, keyword) => generateFilterPred(acc, contentField.FieldName, keyword, 0)); // predicate for boosting var boostPred = searchTarget.Fields .Where(field => field.Boost > 0.0f) .SelectMany(_ => keywords, (field, keyword) => (field, keyword)) .Aggregate( PredicateBuilder.Create <T>(item => item.Name.MatchWildcard("*").Boost(0)), // always true (acc, pair) => generateBoostPred(acc, pair.field.Name, pair.keyword, pair.field.Boost)); return(query.Filter(filterPred).Where(boostPred)); }
public static IQueryable <T> CreateKeywordSearchQuery <T>(this IProviderSearchContext context, string searchTargetId, ICollection <string> keywords, KeywordSearchOptions options = null) where T : SearchResultItem { Assert.ArgumentNotNull(context, nameof(context)); Assert.ArgumentNotNullOrEmpty(searchTargetId, nameof(searchTargetId)); Assert.ArgumentNotNull(keywords, nameof(keywords)); var query = context.GetQueryable <T>(); return(context.AddKeywordSearchQuery(query, searchTargetId, keywords, options)); }