| using Lucene.Net.Analysis; |
| using Lucene.Net.Documents; |
| using Lucene.Net.QueryParsers.Flexible.Core; |
| using Lucene.Net.QueryParsers.Flexible.Core.Config; |
| using Lucene.Net.QueryParsers.Flexible.Standard.Builders; |
| using Lucene.Net.QueryParsers.Flexible.Standard.Config; |
| using Lucene.Net.QueryParsers.Flexible.Standard.Parser; |
| using Lucene.Net.QueryParsers.Flexible.Standard.Processors; |
| using Lucene.Net.Search; |
| using Lucene.Net.Support; |
| using System; |
| using System.Collections.Generic; |
| using System.Globalization; |
| using Operator = Lucene.Net.QueryParsers.Flexible.Standard.Config.StandardQueryConfigHandler.Operator; |
| |
| namespace Lucene.Net.QueryParsers.Flexible.Standard |
| { |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /// <summary> |
| /// This class is a helper that enables users to easily use the Lucene query |
| /// parser. |
| /// <para/> |
| /// To construct a Query object from a query string, use the |
| /// <see cref="Parse(string, string)"/> method: |
| /// <code> |
| /// StandardQueryParser queryParserHelper = new StandardQueryParser(); |
| /// Query query = queryParserHelper.Parse("a AND b", "defaultField"); |
| /// </code> |
| /// <para/> |
| /// To change any configuration before parsing the query string do, for example: |
| /// <code> |
| /// // the query config handler returned by StandardQueryParser is a |
| /// // StandardQueryConfigHandler |
| /// queryParserHelper.QueryConfigHandler.Analyzer = new WhitespaceAnalyzer(); |
| /// </code> |
| /// <para/> |
| /// The syntax for query strings is as follows (copied from the old QueryParser |
| /// javadoc): |
| /// <para/> |
| /// A Query is a series of clauses. A clause may be prefixed by: |
| /// <list type="bullet"> |
| /// <item><description> |
| /// a plus (<c>+</c>) or a minus (<c>-</c>) sign, indicating that |
| /// the clause is required or prohibited respectively; or |
| /// </description></item> |
| /// <item><description> |
| /// a term followed by a colon, indicating the field to be searched. This |
| /// enables one to construct queries which search multiple fields. |
| /// </description></item> |
| /// </list> |
| /// |
| /// A clause may be either: |
| /// <list type="bullet"> |
| /// <item><description> |
| /// a term, indicating all the documents that contain this term; or |
| /// </description></item> |
| /// <item><description> |
| /// a nested query, enclosed in parentheses. Note that this may be used with |
| /// a <c>+</c>/<c>-</c> prefix to require any of a set of terms. |
| /// </description></item> |
| /// </list> |
| /// |
| /// Thus, in BNF, the query grammar is: |
| /// <code> |
| /// Query ::= ( Clause )* |
| /// Clause ::= ["+", "-"] [<TERM> ":"] ( <TERM> | "(" Query ")" ) |
| /// </code> |
| /// |
| /// <para> |
| /// Examples of appropriately formatted queries can be found in the query syntax documentation. |
| /// </para> |
| /// <para> |
| /// The text parser used by this helper is a <see cref="StandardSyntaxParser"/>. |
| /// </para> |
| /// <para> |
| /// The query node processor used by this helper is a |
| /// <see cref="StandardQueryNodeProcessorPipeline"/>. |
| /// </para> |
| /// <para> |
| /// The builder used by this helper is a <see cref="StandardQueryTreeBuilder"/>. |
| /// </para> |
| /// </summary> |
| /// <seealso cref="StandardQueryParser"/> |
| /// <seealso cref="StandardQueryConfigHandler"/> |
| /// <seealso cref="StandardSyntaxParser"/> |
| /// <seealso cref="StandardQueryNodeProcessorPipeline"/> |
| /// <seealso cref="StandardQueryTreeBuilder"/> |
| public class StandardQueryParser : QueryParserHelper<Query>, ICommonQueryParserConfiguration |
| { |
| /// <summary> |
| /// Constructs a <see cref="StandardQueryParser"/> object. |
| /// </summary> |
| public StandardQueryParser() |
| : base(new StandardQueryConfigHandler(), new StandardSyntaxParser(), |
| new StandardQueryNodeProcessorPipeline(null), |
| new StandardQueryTreeBuilder()) |
| { |
| EnablePositionIncrements = true; |
| } |
| |
| /// <summary> |
| /// Constructs a <see cref="StandardQueryParser"/> object and sets an |
| /// <see cref="Analysis.Analyzer"/> to it. The same as: |
| /// <code> |
| /// StandardQueryParser qp = new StandardQueryParser(); |
| /// qp.QueryConfigHandler.Analyzer = analyzer; |
| /// </code> |
| /// </summary> |
| /// <param name="analyzer">the analyzer to be used by this query parser helper</param> |
| public StandardQueryParser(Analyzer analyzer) |
| : this() |
| { |
| this.Analyzer = analyzer; |
| } |
| |
| public override string ToString() |
| { |
| return "<StandardQueryParser config=\"" + this.QueryConfigHandler |
| + "\"/>"; |
| } |
| |
| /// <summary> |
| /// Overrides <see cref="QueryParserHelper{TQuery}.Parse(string, string)"/> so it casts the |
| /// return object to <see cref="Query"/>. For more reference about this method, check |
| /// <see cref="QueryParserHelper{TQuery}.Parse(string, string)"/>. |
| /// </summary> |
| /// <param name="query">the query string</param> |
| /// <param name="defaultField">the default field used by the text parser</param> |
| /// <returns>the object built from the query</returns> |
| /// <exception cref="QueryNodeException">if something wrong happens along the three phases</exception> |
| public override Query Parse(string query, string defaultField) |
| { |
| return base.Parse(query, defaultField); |
| } |
| |
| /// <summary> |
| /// Gets or Sets the boolean operator of the QueryParser. In default mode ( |
| /// <see cref="Operator.OR"/>) terms without any modifiers are considered optional: |
| /// for example <c>capital of Hungary</c> is equal to |
| /// <c>capital OR of OR Hungary</c>. |
| /// <para/> |
| /// In <see cref="Operator.AND"/> mode terms are considered to be in conjunction: the |
| /// above mentioned query is parsed as <c>capital AND of AND Hungary</c> |
| /// </summary> |
| public virtual Operator DefaultOperator |
| { |
| get => QueryConfigHandler.Get(ConfigurationKeys.DEFAULT_OPERATOR); |
| set => QueryConfigHandler.Set(ConfigurationKeys.DEFAULT_OPERATOR, value); |
| } |
| |
| /// <summary> |
| /// Set to <c>true</c> to allow leading wildcard characters. |
| /// <para/> |
| /// When set, <c>*</c> or <c>?</c> are allowed as the first |
| /// character of a <see cref="PrefixQuery"/> and <see cref="WildcardQuery"/>. Note that this can produce |
| /// very slow queries on big indexes. |
| /// <para/> |
| /// Default: false. |
| /// </summary> |
| public virtual bool LowercaseExpandedTerms |
| { |
| get => QueryConfigHandler.Get(ConfigurationKeys.LOWERCASE_EXPANDED_TERMS) ?? true; |
| set => QueryConfigHandler.Set(ConfigurationKeys.LOWERCASE_EXPANDED_TERMS, value); |
| } |
| |
| /// <summary> |
| /// Set to <c>true</c> to allow leading wildcard characters. |
| /// <para/> |
| /// When set, <c>*</c> or <c>?</c> are allowed as the first |
| /// character of a <see cref="PrefixQuery"/> and <see cref="WildcardQuery"/>. Note that this can produce |
| /// very slow queries on big indexes. |
| /// <para/> |
| /// Default: false. |
| /// </summary> |
| public virtual bool AllowLeadingWildcard |
| { |
| get => QueryConfigHandler.Get(ConfigurationKeys.ALLOW_LEADING_WILDCARD) ?? false; |
| set => QueryConfigHandler.Set(ConfigurationKeys.ALLOW_LEADING_WILDCARD, value); |
| } |
| |
| /// <summary> |
| /// Set to <c>true</c> to enable position increments in result query. |
| /// <para/> |
| /// When set, result phrase and multi-phrase queries will be aware of position |
| /// increments. Useful when e.g. a <see cref="Analysis.Core.StopFilter"/> increases the position increment |
| /// of the token that follows an omitted token. |
| /// <para/> |
| /// Default: false. |
| /// </summary> |
| public virtual bool EnablePositionIncrements |
| { |
| get => QueryConfigHandler.Get(ConfigurationKeys.ENABLE_POSITION_INCREMENTS) ?? false; |
| set => QueryConfigHandler.Set(ConfigurationKeys.ENABLE_POSITION_INCREMENTS, value); |
| } |
| |
| /// <summary> |
| /// By default, it uses |
| /// <see cref="MultiTermQuery.CONSTANT_SCORE_AUTO_REWRITE_DEFAULT"/> when creating a |
| /// prefix, wildcard and range queries. This implementation is generally |
| /// preferable because it a) Runs faster b) Does not have the scarcity of terms |
| /// unduly influence score c) avoids any Exception due to too many listeners. |
| /// However, if your application really needs to use the |
| /// old-fashioned boolean queries expansion rewriting and the above points are |
| /// not relevant then use this change the rewrite method. |
| /// </summary> |
| public virtual MultiTermQuery.RewriteMethod MultiTermRewriteMethod |
| { |
| get => QueryConfigHandler.Get(ConfigurationKeys.MULTI_TERM_REWRITE_METHOD); |
| set => QueryConfigHandler.Set(ConfigurationKeys.MULTI_TERM_REWRITE_METHOD, value); |
| } |
| |
| /// <summary> |
| /// Set the fields a query should be expanded to when the field is |
| /// <c>null</c> |
| /// </summary> |
| /// <param name="fields">the fields used to expand the query</param> |
| public virtual void SetMultiFields(string[] fields) |
| { |
| |
| if (fields == null) |
| { |
| fields = Arrays.Empty<string>(); |
| } |
| |
| QueryConfigHandler.Set(ConfigurationKeys.MULTI_FIELDS, fields); |
| |
| } |
| |
| /// <summary> |
| /// Returns the fields used to expand the query when the field for a |
| /// certain query is <c>null</c> |
| /// </summary> |
| /// <returns>the fields used to expand the query</returns> |
| public virtual string[] GetMultiFields() |
| { |
| return QueryConfigHandler.Get(ConfigurationKeys.MULTI_FIELDS); |
| } |
| |
| /// <summary> |
| /// Gets or Sets the prefix length for fuzzy queries. Default is 0. |
| /// </summary> |
| public virtual int FuzzyPrefixLength |
| { |
| get |
| { |
| FuzzyConfig fuzzyConfig = QueryConfigHandler.Get(ConfigurationKeys.FUZZY_CONFIG); |
| |
| if (fuzzyConfig == null) |
| { |
| return FuzzyQuery.DefaultPrefixLength; |
| } |
| else |
| { |
| return fuzzyConfig.PrefixLength; |
| } |
| } |
| set |
| { |
| QueryConfigHandler config = QueryConfigHandler; |
| FuzzyConfig fuzzyConfig = config.Get(ConfigurationKeys.FUZZY_CONFIG); |
| |
| if (fuzzyConfig == null) |
| { |
| fuzzyConfig = new FuzzyConfig(); |
| config.Set(ConfigurationKeys.FUZZY_CONFIG, fuzzyConfig); |
| } |
| |
| fuzzyConfig.PrefixLength = value; |
| } |
| } |
| |
| public virtual IDictionary<string, NumericConfig> NumericConfigMap |
| { |
| get => QueryConfigHandler.Get(ConfigurationKeys.NUMERIC_CONFIG_MAP); |
| set => QueryConfigHandler.Set(ConfigurationKeys.NUMERIC_CONFIG_MAP, value); |
| } |
| |
| /// <summary> |
| /// Gets or Sets current locale, allowing access by subclasses. Used by date range parsing |
| /// </summary> |
| public virtual CultureInfo Locale |
| { |
| get |
| { |
| var culture = QueryConfigHandler.Get(ConfigurationKeys.LOCALE); |
| return culture ?? CultureInfo.CurrentCulture; |
| } |
| set => QueryConfigHandler.Set(ConfigurationKeys.LOCALE, value); |
| } |
| |
| public virtual TimeZoneInfo TimeZone |
| { |
| get => QueryConfigHandler.Get(ConfigurationKeys.TIMEZONE) ?? TimeZoneInfo.Local; |
| set => QueryConfigHandler.Set(ConfigurationKeys.TIMEZONE, value); |
| } |
| |
| /// <summary> |
| /// Sets the default slop for phrases. If zero, then exact phrase matches are |
| /// required. Default value is zero. |
| /// </summary> |
| /// <param name="defaultPhraseSlop"></param> |
| [Obsolete("Use PhraseSlop property setter instead.")] |
| public virtual void SetDefaultPhraseSlop(int defaultPhraseSlop) |
| { |
| QueryConfigHandler.Set(ConfigurationKeys.PHRASE_SLOP, defaultPhraseSlop); |
| } |
| |
| public virtual Analyzer Analyzer |
| { |
| get => QueryConfigHandler.Get(ConfigurationKeys.ANALYZER); |
| set => QueryConfigHandler.Set(ConfigurationKeys.ANALYZER, value); |
| } |
| |
| /// <summary> |
| /// Gets or Sets the default slop for phrases. If zero, then exact phrase matches are |
| /// required. Default value is zero. NOTE: Setter is deprecated. |
| /// </summary> |
| public virtual int PhraseSlop |
| { |
| get => QueryConfigHandler.Get(ConfigurationKeys.PHRASE_SLOP) ?? 0; |
| set => QueryConfigHandler.Set(ConfigurationKeys.PHRASE_SLOP, value); |
| } |
| |
| /// <summary> |
| /// Gets or Sets the minimum similarity for fuzzy queries. Default is defined on |
| /// <see cref="FuzzyQuery.DefaultMinSimilarity"/>. |
| /// </summary> |
| public virtual float FuzzyMinSim |
| { |
| get |
| { |
| FuzzyConfig fuzzyConfig = QueryConfigHandler.Get(ConfigurationKeys.FUZZY_CONFIG); |
| return (fuzzyConfig != null) ? fuzzyConfig.MinSimilarity |
| #pragma warning disable 612, 618 |
| : FuzzyQuery.DefaultMinSimilarity; |
| #pragma warning restore 612, 618 |
| } |
| set |
| { |
| QueryConfigHandler config = QueryConfigHandler; |
| FuzzyConfig fuzzyConfig = config.Get(ConfigurationKeys.FUZZY_CONFIG); |
| |
| if (fuzzyConfig == null) |
| { |
| fuzzyConfig = new FuzzyConfig(); |
| config.Set(ConfigurationKeys.FUZZY_CONFIG, fuzzyConfig); |
| } |
| |
| fuzzyConfig.MinSimilarity = value; |
| } |
| } |
| |
| /// <summary> |
| /// Gets or Sets the field to boost map used to set boost for each field. |
| /// </summary> |
| public virtual IDictionary<string, float?> FieldsBoost |
| { |
| get => QueryConfigHandler.Get(ConfigurationKeys.FIELD_BOOST_MAP); |
| set => QueryConfigHandler.Set(ConfigurationKeys.FIELD_BOOST_MAP, value); |
| } |
| |
| /// <summary> |
| /// Sets the default <see cref="DateTools.Resolution"/> used for certain field when |
| /// no <see cref="DateTools.Resolution"/> is defined for this field. |
| /// </summary> |
| /// <param name="dateResolution">the default <see cref="DateTools.Resolution"/></param> |
| // LUCENENET NOTE: This method is required by the ICommonQueryParserConfiguration interface |
| public virtual void SetDateResolution(DateTools.Resolution dateResolution) |
| { |
| QueryConfigHandler.Set(ConfigurationKeys.DATE_RESOLUTION, dateResolution); |
| } |
| |
| /// <summary> |
| /// Gets the default <see cref="DateTools.Resolution"/> used for certain field when |
| /// no <see cref="DateTools.Resolution"/> is defined for this field. |
| /// </summary> |
| public virtual DateTools.Resolution DateResolution => QueryConfigHandler.Get(ConfigurationKeys.DATE_RESOLUTION); |
| |
| /// <summary> |
| /// Sets the <see cref="DateTools.Resolution"/> used for each field |
| /// </summary> |
| /// <param name="dateRes">a collection that maps a field to its <see cref="DateTools.Resolution"/></param> |
| [Obsolete("Use DateResolutionMap property instead.")] |
| public virtual void SetDateResolution(IDictionary<string, DateTools.Resolution?> dateRes) |
| { |
| DateResolutionMap = dateRes; |
| } |
| |
| /// <summary> |
| /// Gets or Sets the field to <see cref="T:DateTools.Resolution?"/> map used to normalize each date field. |
| /// </summary> |
| public virtual IDictionary<string, DateTools.Resolution?> DateResolutionMap |
| { |
| get => QueryConfigHandler.Get(ConfigurationKeys.FIELD_DATE_RESOLUTION_MAP); |
| set => QueryConfigHandler.Set(ConfigurationKeys.FIELD_DATE_RESOLUTION_MAP, value); |
| } |
| } |
| } |