Exemple #1
0
        private IEnumerable <LocationItemPage> GetRelatedLocations(LocationItemPage currentPage)
        {
            IQueriedSearch <LocationItemPage> query = SearchClient.Instance
                                                      .Search <LocationItemPage>()
                                                      .MoreLike(SearchTextFly(currentPage))
                                                      .BoostMatching(x =>
                                                                     x.Country.Match(currentPage.Country ?? ""), 2)
                                                      .BoostMatching(x =>
                                                                     x.Continent.Match(currentPage.Continent ?? ""), 1.5)
                                                      .BoostMatching(x =>
                                                                     x.Coordinates
                                                                     .WithinDistanceFrom(currentPage.Coordinates ?? new GeoLocation(0, 0),
                                                                                         1000.Kilometers()), 2.5);

            query = currentPage.Category.Aggregate(query,
                                                   (current, category) =>
                                                   current.BoostMatching(x => x.InCategory(category), 1.5));

            return(query
                   .Filter(x => !x.PageLink.Match(currentPage.PageLink))
                   .PublishedInCurrentLanguage()
                   .FilterForVisitor()
                   .Take(3)
                   .GetPagesResult());
        }
Exemple #2
0
 /// <summary>
 /// Adds content type boosts to the search.
 /// </summary>
 /// <typeparam name="T">The type to query for.</typeparam>
 /// <param name="query">The query.</param>
 /// <param name="favoriteUserContent">The content types to boost, with the boost factor.</param>
 /// <returns>The <see cref="IQueriedSearch{T}"/> with added BoostMatching.</returns>
 /// <remarks><para>The BoostMatching method must be called before any method not related to the search query (such as Filter, Take, and Skip).</para>
 /// <para>This is enforced by the fact that the For method in the above sample returns a IQueriedSearch object.</para>
 /// </remarks>
 public static IQueriedSearch <T> AddContentTypeBoosts <T>(
     this IQueriedSearch <T> query,
     Dictionary <int, int> favoriteUserContent)
     where T : IContent
 {
     return(favoriteUserContent.Aggregate(
                query,
                (current, favoriteContent) => current.BoostMatching(x => x.ContentTypeID.Match(favoriteContent.Key), favoriteContent.Value)));
 }
Exemple #3
0
 /// <summary>
 /// Adds category boosts to the search.
 /// </summary>
 /// <typeparam name="T">The type to query for.</typeparam>
 /// <param name="query">The query.</param>
 /// <param name="favoriteCategories">The categories to boost, with the boost factor.</param>
 /// <returns>The <see cref="IQueriedSearch{T}"/> with added BoostMatching.</returns>
 /// <remarks><para>The BoostMatching method must be called before any method not related to the search query (such as Filter, Take, and Skip).</para>
 /// <para>This is enforced by the fact that the For method in the above sample returns a IQueriedSearch object.</para>
 /// </remarks>
 public static IQueriedSearch <T> AddCategoryBoosts <T>(
     this IQueriedSearch <T> query,
     Dictionary <int, int> favoriteCategories)
     where T : ICategorizable
 {
     return(favoriteCategories.Aggregate(
                query,
                (current, favoriteCategory) => current.BoostMatching(x => x.Category.In(new[] { favoriteCategory.Key }), favoriteCategory.Value)));
 }
        static void SearchEverythingFor(string q)
        {
            WriteLine($"* Search for everything with: {q}");

            ITypeSearch <object> search = client.Search <object>();

            // perform a "free text" query
            IQueriedSearch <object> query = search.For(q);

            OutputResults(query as ITypeSearch <object>);
        }
        static void SearchBooksFor(string q)
        {
            WriteLine($"* Search for books with: {q}");

            // only look for "books" and allow word stemming
            ITypeSearch <Book> search = client.Search <Book>(Language.English);

            // perform a "free text" query looking in Title and Description
            IQueriedSearch <Book> query = search.For(q)
                                          .InField(x => x.Title, 3.0) // triple the weighting for matches in Title
                                          .InField(x => x.Description);

            OutputResults(query as ITypeSearch <Book>);
        }
Exemple #6
0
        public static bool TryGetQueryStringQuery <TSource>(IQuery query, IQueriedSearch <TSource> search, out MultiFieldQueryStringQuery currentQueryStringQuery)
        {
            currentQueryStringQuery = query as MultiFieldQueryStringQuery;
            if (currentQueryStringQuery == null)
            {
                // Synonyms are only supported for QueryStringQuery
                Find.Tracing.Trace.Instance.Add(new TraceEvent(search, "The use of synonyms are only supported för QueryStringQueries, i.e. with the use of the .For() -extensions. The query will be executed without the use of synonyms.")
                {
                    IsError = false
                });
                return(false);
            }

            return(true);
        }
Exemple #7
0
 /// <summary>
 /// Searches for the specified query in all default search fields, and in the specified locale.
 /// </summary>
 /// <param name="search">The search to modify.</param>
 /// <param name="query">The query text to search for.</param>
 /// <param name="locale">The locale to search in.</param>
 /// <returns>The search, modified to include the requested query.</returns>
 public static ITypeSearch <FindDocument> ForDefaultFields(this ITypeSearch <FindDocument> search, string query, string locale)
 {
     if (!string.IsNullOrEmpty(query))
     {
         ISearchConfiguration configuration = search.Client.GetConfiguration();
         IQueriedSearch <FindDocument, QueryStringQuery> search1 = search.For <FindDocument>(query);
         Enumerable.Empty <IFieldConfiguration>();
         foreach (IFieldConfiguration fieldConfiguration1 in !string.IsNullOrWhiteSpace(locale) ? configuration.GetDefaultFields(locale) : configuration.GetDefaultFields())
         {
             if (fieldConfiguration1.Type == typeof(string))
             {
                 IFieldConfiguration <string> fieldConfiguration2 = (IFieldConfiguration <string>)fieldConfiguration1;
                 search1 = search1.InField <FindDocument, QueryStringQuery>(fieldConfiguration2.TypedGetValueExpression, new double?());
             }
             else if (fieldConfiguration1.Type == typeof(IEnumerable <string>))
             {
                 IFieldConfiguration <IEnumerable <string> > fieldConfiguration2 = (IFieldConfiguration <IEnumerable <string> >)fieldConfiguration1;
                 search1 = search1.InField <FindDocument, QueryStringQuery>(fieldConfiguration2.TypedGetValueExpression, new double?());
             }
             else if (fieldConfiguration1.Type == typeof(int?))
             {
                 IFieldConfiguration <int?> fieldConfiguration2 = (IFieldConfiguration <int?>)fieldConfiguration1;
                 search1 = search1.InField <FindDocument, QueryStringQuery>(fieldConfiguration2.TypedGetValueExpression, new double?());
             }
             else if (fieldConfiguration1.Type == typeof(int))
             {
                 IFieldConfiguration <int> fieldConfiguration2 = (IFieldConfiguration <int>)fieldConfiguration1;
                 search1 = search1.InField <FindDocument, QueryStringQuery>(fieldConfiguration2.TypedGetValueExpression, new double?());
             }
             else if (fieldConfiguration1.Type == typeof(double?) || fieldConfiguration1.Type == typeof(float?))
             {
                 IFieldConfiguration <double?> fieldConfiguration2 = (IFieldConfiguration <double?>)fieldConfiguration1;
                 search1 = search1.InField <FindDocument, QueryStringQuery>(fieldConfiguration2.TypedGetValueExpression, new double?());
             }
             else
             {
                 if (!(fieldConfiguration1.Type == typeof(double)) && !(fieldConfiguration1.Type == typeof(float)))
                 {
                     throw new Exception(string.Format((IFormatProvider)CultureInfo.InvariantCulture, "Field of type {0} is not valid for the default search.", (object)fieldConfiguration1.Type.Name));
                 }
                 IFieldConfiguration <double> fieldConfiguration2 = (IFieldConfiguration <double>)fieldConfiguration1;
                 search1 = search1.InField <FindDocument, QueryStringQuery>(fieldConfiguration2.TypedGetValueExpression, new double?());
             }
         }
         search = (ITypeSearch <FindDocument>)search1;
     }
     return(search);
 }
        public static IQueriedSearch <TSource, QueryStringQuery> UsingRelevanceImproved <TSource>(this IQueriedSearch <TSource> search, params Expression <Func <TSource, string> >[] fieldSelectors)
        {
            return(new Search <TSource, QueryStringQuery>(search, context =>
            {
                BoolQuery currentBoolQuery;
                BoolQuery newBoolQuery = new BoolQuery();
                MinShouldMatchQueryStringQuery currentQueryStringQuery;

                if (QueryHelpers.TryGetBoolQuery(context.RequestBody.Query, out currentBoolQuery))
                {
                    if (!QueryHelpers.TryGetMinShouldMatchQueryStringQuery(currentBoolQuery.Should[0], out currentQueryStringQuery))
                    {
                        return;
                    }
                    newBoolQuery = currentBoolQuery;
                }
                else
                {
                    currentBoolQuery = new BoolQuery();
                    if (!QueryHelpers.TryGetMinShouldMatchQueryStringQuery(context.RequestBody.Query, out currentQueryStringQuery))
                    {
                        return;
                    }
                    newBoolQuery.Should.Add(currentQueryStringQuery);
                }

                // If .UsingImprovedSynonyms has not been used there is no ExpandedQuery for us then we use the query
                if (currentQueryStringQuery.ExpandedQuery.IsNull())
                {
                    currentQueryStringQuery.ExpandedQuery = new string[] { currentQueryStringQuery.Query.ToString().Replace("¤", " ") };
                }

                foreach (var query in currentQueryStringQuery.ExpandedQuery)
                {
                    var terms = QueryHelpers.GetQueryPhrases(query);

                    foreach (var fieldSelector in fieldSelectors)
                    {
                        var fieldNameLowercase = search.Client.Conventions.FieldNameConvention.GetFieldNameForLowercase(fieldSelector);
                        var fieldNameAnalyzed = search.Client.Conventions.FieldNameConvention.GetFieldNameForAnalyzed(fieldSelector);

                        // Create PrefixQuery for single term queries larger than 2 characters
                        if (terms.Count() == 1 && terms.First().Length > 2)
                        {
                            var prefixQuery = new PrefixQuery(fieldNameLowercase, query.ToLower())
                            {
                                Boost = 0.5
                            };
                            newBoolQuery.Should.Add(prefixQuery);
                        }

                        // Create PhraseQuery and PhrasePrefixQuery for multiple term queries
                        if (terms.Count() > 1)
                        {
                            var phraseQuery = new PhraseQuery(fieldNameAnalyzed, query)
                            {
                                Boost = 5
                            };
                            var phrasePrefixQuery = new PhrasePrefixQuery(fieldNameLowercase, query.ToLower())
                            {
                                Boost = 10
                            };
                            newBoolQuery.Should.Add(phraseQuery);
                            newBoolQuery.Should.Add(phrasePrefixQuery);
                        }
                    }
                }

                if (newBoolQuery.Should.Count == 0)
                {
                    return;
                }

                context.RequestBody.Query = newBoolQuery;
            }));
        }
        public static IQueriedSearch <TSource, MinShouldMatchQueryStringQuery> MinimumShouldMatch <TSource>(this IQueriedSearch <TSource> search, string minMatch)
        {
            return(new Search <TSource, MinShouldMatchQueryStringQuery>(search, context =>
            {
                var originalQuery = (QueryStringQuery)context.RequestBody.Query;
                var query = new MinShouldMatchQueryStringQuery(originalQuery.Query);
                query.RawQuery = originalQuery.RawQuery;
                query.AllowLeadingWildcard = originalQuery.AllowLeadingWildcard;
                query.AnalyzeWildcard = originalQuery.AnalyzeWildcard;
                query.Analyzer = originalQuery.Analyzer;
                query.AutoGeneratePhraseQueries = originalQuery.AutoGeneratePhraseQueries;
                query.Boost = originalQuery.Boost;
                query.DefaultOperator = originalQuery.DefaultOperator;
                query.EnablePositionIncrements = originalQuery.EnablePositionIncrements;
                query.FuzzyMinSim = originalQuery.FuzzyMinSim;
                query.FuzzyPrefixLength = originalQuery.FuzzyPrefixLength;
                query.LowercaseExpandedTerms = originalQuery.LowercaseExpandedTerms;
                query.PhraseSlop = originalQuery.PhraseSlop;
                query.DefaultField = originalQuery.DefaultField;
                var multiFieldQuery = context.RequestBody.Query as MultiFieldQueryStringQuery;
                if (multiFieldQuery != null)
                {
                    query.Fields = multiFieldQuery.Fields;
                }
                query.MinimumShouldMatch = minMatch;

                context.RequestBody.Query = query;
            }));
        }
 public static IQueriedSearch <TSource, QueryStringQuery> UsingSynonymsImproved <TSource>(this IQueriedSearch <TSource> search, UsingSynonymService usingSynonymService, TimeSpan?cacheDuration = null)
 {
     return(usingSynonymService.UsingSynonyms(search, cacheDuration));
 }
        public static IQueriedSearch <TSource, QueryStringQuery> WildcardMatch <TSource>(this IQueriedSearch <TSource> search, params Expression <Func <TSource, string> >[] fieldSelectors)
        {
            return(new Search <TSource, QueryStringQuery>(search, context =>
            {
                BoolQuery currentBoolQuery;
                BoolQuery newBoolQuery = new BoolQuery();
                MinShouldMatchQueryStringQuery currentQueryStringQuery;

                if (QueryHelpers.TryGetBoolQuery(context.RequestBody.Query, out currentBoolQuery))
                {
                    if (!QueryHelpers.TryGetMinShouldMatchQueryStringQuery(currentBoolQuery.Should[0], out currentQueryStringQuery))
                    {
                        return;
                    }
                    newBoolQuery = currentBoolQuery;
                }
                else
                {
                    if (!QueryHelpers.TryGetMinShouldMatchQueryStringQuery(context.RequestBody.Query, out currentQueryStringQuery))
                    {
                        return;
                    }
                    newBoolQuery.Should.Add(currentQueryStringQuery);
                }

                var query = QueryHelpers.GetRawQueryString(currentQueryStringQuery);
                if (query.IsNullOrEmpty())
                {
                    return;
                }

                // Do not trigger on synonym expansions which are parenthesized and not on quoted searches.
                if (IsParenthesized(query) || QueryHelpers.IsStringQuoted(query))
                {
                    return;
                }

                var terms = QueryHelpers.GetQueryPhrases(query);

                // Only take terms > 2 chars and take max 3 of these
                string[] candidateTerms = terms.Where(x => x.Length > 2).Take(3).Select(x => string.Format("{0}{1}", x, "*")).ToArray();
                if (candidateTerms.Count() == 0)
                {
                    return;
                }

                List <string> fieldNames = new List <string>();
                foreach (var fieldSelector in fieldSelectors)
                {
                    string fieldName = search.Client.Conventions
                                       .FieldNameConvention
                                       .GetFieldNameForAnalyzed(fieldSelector);
                    fieldNames.Add(fieldName);
                }

                var wildcardQueryString = string.Join(" ", candidateTerms);
                var wildcardQuery = new MinShouldMatchQueryStringQuery(wildcardQueryString)
                {
                    Fields = fieldNames,
                    DefaultOperator = currentQueryStringQuery.DefaultOperator,
                    MinimumShouldMatch = currentQueryStringQuery.MinimumShouldMatch,
                    Boost = 0.2
                };

                newBoolQuery.Should.Add(wildcardQuery);

                context.RequestBody.Query = newBoolQuery;
            }));
        }
 public static IQueriedSearch <TSource, QueryStringQuery> UsingSynonymsImproved <TSource>(this IQueriedSearch <TSource> search, TimeSpan?cacheDuration = null)
 {
     return(UsingSynonymsImproved(search, _lazyUsingSynonymService.Value, cacheDuration));
 }
        public IQueriedSearch <TSource, QueryStringQuery> UsingSynonyms <TSource>(IQueriedSearch <TSource> search, TimeSpan?cacheDuration = null)
        {
            if (search.Client.Settings.Admin)
            {
                return(new Search <TSource, QueryStringQuery>(search, context =>
                {
                    if (context.RequestBody.Query != null)
                    {
                        BoolQuery newBoolQuery = new BoolQuery();
                        BoolQuery currentBoolQuery;
                        MultiFieldQueryStringQuery currentQueryStringQuery;

                        if (QueryHelpers.TryGetBoolQuery(context.RequestBody.Query, out currentBoolQuery))
                        {
                            if (!QueryHelpers.TryGetQueryStringQuery(currentBoolQuery.Should[0], search, out currentQueryStringQuery))
                            {
                                return;
                            }
                        }
                        else
                        {
                            if (!QueryHelpers.TryGetQueryStringQuery(context.RequestBody.Query, search, out currentQueryStringQuery))
                            {
                                return;
                            }
                        }

                        var query = QueryHelpers.GetQueryString(currentQueryStringQuery);
                        if (query.IsNullOrEmpty())
                        {
                            return;
                        }

                        // If MinimumShouldMatch has been set previously pick up the minShouldMatch value
                        MinShouldMatchQueryStringQuery currentMinShouldMatchQueryStringQuery;
                        string minShouldMatch = "";
                        if (QueryHelpers.TryGetMinShouldMatchQueryStringQuery(currentQueryStringQuery, out currentMinShouldMatchQueryStringQuery))
                        {
                            minShouldMatch = currentMinShouldMatchQueryStringQuery.MinimumShouldMatch;
                        }

                        var synonymDictionary = _synonymLoader.GetSynonyms(cacheDuration);

                        var queryPhrases = QueryHelpers.GetQueryPhrases(query).ToArray();
                        if (queryPhrases.Count() == 0)
                        {
                            return;
                        }

                        HashSet <string> queriesForMatch;
                        string queryNotExpanded = string.Join(" ", queryPhrases);
                        string queryExpanded;

                        if (!GetQueryExpanded(queryPhrases, synonymDictionary, out queryExpanded, out queriesForMatch))
                        {
                            return;
                        }

                        // Add non expanded query. Using the custom MinimumShouldMatch if set.
                        if (queryNotExpanded.IsNotNullOrEmpty())
                        {
                            var minShouldMatchQuery = CreateQuery(queryNotExpanded, currentQueryStringQuery, "");

                            // MinimumShouldMatch() overrides WithAndAsDefaultOperator()
                            if (minShouldMatch.IsNotNullOrEmpty())
                            {
                                minShouldMatchQuery.MinimumShouldMatch = minShouldMatch;
                            }
                            // Emulate WithAndAsDefaultOperator() using MinimumShouldMatch set to 100%
                            else if (currentQueryStringQuery.DefaultOperator == BooleanOperator.And)
                            {
                                minShouldMatchQuery.MinimumShouldMatch = "100%";
                            }

                            // We save all variations of queries with and without synonym expansions
                            // to be picked up by UsingImprovedRelevance()
                            // Only allow for 3 queriesForMatch
                            minShouldMatchQuery.ExpandedQuery = queriesForMatch.Take(3).ToArray();
                            newBoolQuery.Should.Add(minShouldMatchQuery);
                        }

                        // Add expanded query. MinimumShouldMatch is always 1 here.
                        if (queryExpanded.IsNotNullOrEmpty())
                        {
                            var minShouldMatchQuery = CreateQuery(queryExpanded, currentQueryStringQuery, "1");
                            newBoolQuery.Should.Add(minShouldMatchQuery);
                        }

                        if (newBoolQuery.IsNull())
                        {
                            return;
                        }

                        // Keep all QueryStringQuery except the first Should generated by For()
                        if (currentBoolQuery.IsNotNull())
                        {
                            foreach (var currentQuery in currentBoolQuery.Should.Skip(1))
                            {
                                newBoolQuery.Should.Add(currentQuery);
                            }

                            foreach (var currentQuery in currentBoolQuery.Must)
                            {
                                newBoolQuery.Must.Add(currentQuery);
                            }

                            foreach (var currentQuery in currentBoolQuery.MustNot)
                            {
                                newBoolQuery.MustNot.Add(currentQuery);
                            }
                        }

                        context.RequestBody.Query = newBoolQuery;
                    }
                }));
            }
            else
            {
                Find.Tracing.Trace.Instance.Add(new TraceEvent(search, "Your index does not support synonyms. Please contact support to have your account upgraded. Falling back to search without synonyms.")
                {
                    IsError = false
                });
                return(new Search <TSource, QueryStringQuery>(search, context => { }));
            }
        }