Exemplo n.º 1
0
        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));
        }
Exemplo n.º 2
0
        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));
        }