简体   繁体   English

具有字段优先级的嵌套查询和过滤器查询

[英]Nest queries with field priority and filter query

I am trying build a search functionality with ElasticSearch using Nest. 我正在尝试使用Nest使用ElasticSearch构建搜索功能。 What I need is following: 我需要的是以下内容:

  • I have product table and I indexed is as below: 我有产品表,索引如下:

     foreach (var product in products) { Product product = new Product(product.ProductId, product.Name, product.Number, product.Description); ElasticClient.Index(productes); } 
  • Then I execute following queries: 然后我执行以下查询:

    1. This works fine. 这很好。 I get results. 我得到结果。

       var results = ElasticClient.Search<Product>(body => body.Query(query => query.QueryString(qs => qs.Query(key))).Size(20)); 

      Both none of the below queries work. 以下两个查询都不起作用。 Why? 为什么? What am I doing wrong? 我究竟做错了什么?

    2. - --

       var results = ElasticClient.Search<Product>(body => body.Filter(filter => filter.Term(x => x.Name, key)).Take(1000)); 
    3. - --

       var results = ElasticClient.Search<Product>(s => s .From(0) .Size(15) .Query(q => q .Term(p => p.Name, key))); 
    4. - --

       var results = ElasticClient.Search<Product>(body => body.Query(query => query.ConstantScore(csq => csq.Filter(filter => filter.Term(x => x.Name, key.ToLower())))).Take(1000)); 

I would like to first of all understand why queries with filter don't work for me. 我想首先了解为什么带过滤器的查询对我不起作用。 Finally, I want to achieve a query that searches a given keyword and prioritizes results based on which field (column, property) it was found in. 最后,我想实现一个查询,该查询搜索给定的关键字,并根据找到该字段的字段(列,属性)对结果进行优先级排序。

So if keyword was in the "name" field, it should be returned at the top. 因此,如果关键字位于“名称”字段中,则应在顶部将其返回。 So respectively, "Name", "Number", "Description". 因此分别是“名称”,“编号”,“描述”。 How can I achieve such a query? 如何实现这样的查询?

EDIT: I tried the query below but it doesn't return anything. 编辑:我尝试下面的查询,但它不返回任何内容。

var results = ElasticClient.Search<Product>(body => body
    .Query(q => q
        .QueryString(qs => qs
            .OnFieldsWithBoost(d => d
                .Add(entry => entry.Name, 5.0)
                .Add(entry => entry.Number, 3.0)
                .Add(entry => entry.Description, 2.0))
            .Query(key))));

Below some samples data; 下面是一些样本数据; when I send "2000" as keyword, I get following results with 1. query but others will not return anything. 当我将“ 2000”作为关键字发送时,我得到以下查询结果1.查询,但其他人将不返回任何内容。

在此处输入图片说明

The main reason why the first query returns results and the others don't is because the first query is a query_string and the input keyword (eg 2000 ) will be analyzed and matched with any of your fields (which are also analyzed). 第一个查询返回结果而其他查询不返回结果的主要原因是因为第一个查询是query_string ,并且输入关键字(例如2000 )将被分析并与您的任何字段(也将被分析)匹配。 This is not the case of the second, third and fourth queries because you're using a term query/filter where the input is not analyzed and instead matched as is . 第二,第三和第四次查询不是这种情况,因为您使用的是term查询/过滤器,其中不对输入进行分析,而是按原样进行匹配。

If we take the first document (id=13), the name field will be analyzed and indexed as the following tokens: dr , 2000 , 12k (in lowercase!) as can be seen with the following command: 如果我们采取的第一个文件(ID = 13),该name字段将被分析并索引为下列标记: dr200012k (!小写)作为可以用下面的命令可以看出:

curl -XGET 'localhost:9200/_analyze?pretty&analyzer=standard' -d 'DR-2000 (12k)'

{
  "tokens" : [ {
    "token" : "dr",
    "start_offset" : 0,
    "end_offset" : 2,
    "type" : "<ALPHANUM>",
    "position" : 1
  }, {
    "token" : "2000",
    "start_offset" : 3,
    "end_offset" : 7,
    "type" : "<NUM>",
    "position" : 2
  }, {
    "token" : "12k",
    "start_offset" : 9,
    "end_offset" : 12,
    "type" : "<ALPHANUM>",
    "position" : 3
  } ]
}

So when searching for 2000 (or dr or 12k ) in a query_string query, you'll find that document. 因此,当在query_string查询中搜索2000 (或dr12k )时,您会找到该文档。 Searching for the term 2000 won't yield anything though, which is expected when using term query/filter that work for exact matching. 搜索词2000不会产生任何结果,这在使用能精确匹配的term查询/过滤器时是可以预期的。

As for your second question on boosting fields, the reason that query returns nothing is maybe because the field names are lowercased by default (default behavior of NEST). 至于关于提升字段的第二个问题,查询不返回任何内容的原因可能是因为默认情况下字段名称是小写的 (NEST的默认行为)。 You should make sure to use lowercase field names. 您应该确保使用小写的字段名称。

UPDATE 更新

If you need to perform exact matching, I advise to change your field mappings to multi-field string fields with an analyzed and a not_analyzed field. 如果您需要进行精确匹配,我建议改变你的字段映射到多场串田analyzednot_analyzed场。

{
  "product" : {
    "properties" : {
      "name" : {
        "type" : "string",
        "index" : "analyzed",
        "fields" : {
          "raw" : {"type" : "string", "index" : "not_analyzed"}
        }
      }
    }
  }
}

Then you can query the name field with query_string when you need like behavior and the name.raw field when you need exact match behavior with term query/filter. 然后,当您需要类似行为时,可以使用name.raw查询name字段, query_string当您需要与term查询/过滤器进行完全匹配行为时,可以使用name.raw字段查询。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM