【问题标题】:Creating a custom tokenizer in ElasticSearch NEST在 ElasticSearch NEST 中创建自定义标记器
【发布时间】:2017-05-19 19:06:27
【问题描述】:

我在 ES 2.5 中有以下自定义类:

Title
DataSources
Content

运行搜索很好,除了中间字段 - 它是使用分隔符“|”构建/索引的。

例如:“|4|7|8|9|10|12|14|19|20|21|22|23|29|30”

我需要构建一个匹配所有字段中的一些并且匹配 DataSource 字段中的至少一个数字的查询。

所以总结一下我目前拥有的:

    QueryBase query = new SimpleQueryStringQuery
    {
        //DefaultOperator = !operatorOR ? Operator.And : Operator.Or,
        Fields = LearnAboutFields.FULLTEXT,
        Analyzer = "standard",
        Query = searchWords.ToLower()
    };
    _boolQuery.Must = new QueryContainer[] {query};

这是搜索词查询。

    foreach (var datasource in dataSources)
    {
        // Add DataSources with an OR
        queryContainer |= new WildcardQuery { Field = LearnAboutFields.DATASOURCE, Value = string.Format("*{0}*", datasource) };
    }
    // Add this Boolean Clause to our outer clause with an AND
    _boolQuery.Filter = new QueryContainer[] {queryContainer};
}

这是针对数据源查询的。可以有多个数据源。

它不起作用,并返回添加了过滤查询的结果。我想我需要在标记器/分析器上做一些工作,但我对 ES 的了解还不够,无法弄清楚。

编辑:下面的每个 Val 的 cmets 我试图像这样重新编码索引器:

        _elasticClientWrapper.CreateIndex(_DataSource, i => i
            .Mappings(ms => ms
                .Map<LearnAboutContent>(m => m
                    .Properties(p => p
                        .String(s => s.Name(lac => lac.DataSources)
                            .Analyzer("classic_tokenizer")
                            .SearchAnalyzer("standard")))))
            .Settings(s => s
                .Analysis(an => an.Analyzers(a => a.Custom("classic_tokenizer", ca => ca.Tokenizer("classic"))))));
        var indexResponse = _elasticClientWrapper.IndexMany(contentList);

它成功构建,包含数据。但是查询仍然无法正常工作。

数据源的新查询:

        foreach (var datasource in dataSources)
        {
            // Add DataSources with an OR
            queryContainer |= new TermQuery {Field = LearnAboutFields.DATASOURCE, Value = datasource};
        }
        // Add this Boolean Clause to our outer clause with an AND
        _boolQuery.Must = new QueryContainer[] {queryContainer};

还有 JSON:

{"learnabout_index":{"aliases":{},"mappings":{"learnaboutcontent":{"properties":{"articleID":{"type":"string"},"content":{"type":"string"},"dataSources":{"type":"string","analyzer":"classic_tokenizer","search_analyzer":"standard"},"description":{"type":"string"},"fileName":{"type":"string"},"keywords":{"type":"string"},"linkURL":{"type":"string"},"title":{"type":"string"}}}},"settings":{"index":{"creation_date":"1483992041623","analysis":{"analyzer":{"classic_tokenizer":{"type":"custom","tokenizer":"classic"}}},"number_of_shards":"5","number_of_replicas":"1","uuid":"iZakEjBlRiGfNvaFn-yG-w","version":{"created":"2040099"}}},"warmers":{}}}

查询 JSON 请求:

{
  "size": 10000,
  "query": {
    "bool": {
      "must": [
        {
          "simple_query_string": {
            "fields": [
              "_all"
            ],
            "query": "\"housing\"",
            "analyzer": "standard"
          }
        }
      ],
      "filter": [
        {
          "terms": {
            "DataSources": [
              "1"
            ]
          }
        }
      ]
    }
  }
}

【问题讨论】:

    标签: asp.net elasticsearch nest elasticsearch-2.0 elasticsearch-net


    【解决方案1】:

    实现此目的的一种方法是创建一个带有classic tokenizer 的自定义分析器,它将您的DataSources 字段分解为组成它的数字,即它将标记每个| 字符上的字段。

    因此,当您创建索引时,您需要添加此自定义分析器,然后在您的 DataSources 字段中使用它:

    PUT my_index
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "number_analyzer": {
              "type": "custom",
              "tokenizer": "number_tokenizer"
            }
          },
          "tokenizer": {
            "number_tokenizer": {
              "type": "classic"
            }
          }
        }
      },
      "mappings": { 
        "my_type": {
          "properties": {
            "DataSources": {
              "type": "string",
              "analyzer": "number_analyzer",
              "search_analyzer": "standard"
            }
          }
        }
      }
    }
    

    因此,如果您索引字符串"|4|7|8|9|10|12|14|19|20|21|22|23|29|30",您的DataSources 字段将有效地包含以下令牌数组:[4, 7, 8, 9, 10, 12, 14, 191, 20, 21, 22, 23, 29, 30]

    然后你可以摆脱你的WildcardQuery 并简单地使用TermsQuery 代替:

    terms = new TermsQuery {Field = LearnAboutFields.DATASOURCE, Terms = dataSources }
    // Add this Boolean Clause to our outer clause with an AND
    _boolQuery.Filter = new QueryContainer[] { terms };
    

    【讨论】:

    • 你能提供与上面指定的 JSON 函数等效的 NEST 吗?有没有办法只注释自定义类?
    • 您可以在此处找到等效的示例 NEST:stackoverflow.com/questions/25193800/…
    • 感谢 Val,NEST 示例似乎已过时。是否有更新的版本(至少 2.5)?
    • 很好,您可以运行此程序并使用结果编辑您的问题:curl -XGET localhost:9200/index_name
    • 按要求编辑。
    【解决方案2】:

    乍一看您的代码,我认为您可能遇到的一个问题是,任何放在过滤器子句中的查询都不会被分析。所以基本上这个值不会被分解成token,而是整体比较。

    很容易忘记这一点,因此任何需要分析的值都需要放在 must 或 should 子句中。

    【讨论】:

    • 我很害怕,但我知道即使我将它切换回查询的一部分也没关系 - 仍然不起作用。
    猜你喜欢
    • 1970-01-01
    • 2014-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-19
    相关资源
    最近更新 更多