Elasticsearch 和 C# - 查询以查找字符串的精确匹配

Elasticsearch and C# - query to find exact matches over strings

我需要一种方法来使用 "string" 和 "integer" 类型的两个或多个字段的完全精确匹配来搜索文档。

我想避免使用标准查询,因为我不关心得分或最佳匹配,只关心 yes/no 如果两个字段匹配或不匹配的结果。

我知道我可以使用过滤器来做到这一点,但我只得到了使用 JSON 格式的示例查询。我想在 C# 环境中进行此类搜索。

这是我的映射:

{
   "reviewer-test-index": {
      "aliases": {},
      "mappings": {
         "historyRecord": {
            "properties": {
               "groupName": {
                  "type": "string"
               },
               "groupNo": {
                  "type": "integer"
               },
               "instrType": {
                  "type": "integer"
               },
               "instrumentAddress": {
                  "type": "string"
               },
               "insturmentName": {
                  "type": "string"
               },
               "macAddr": {
                  "type": "string"
               },
               "uhhVersion": {
                  "type": "string"
               }
            }
         },         
      "settings": {
         "index": {
            "creation_date": "1434557536720",
            "number_of_shards": "1",
            "number_of_replicas": "0",
            "version": {
               "created": "1050299"
            },
            "uuid": "FfQADLGVQVOPV3913exKsw"
         }
      },
      "warmers": {}
   }
}

我也尝试进行 JSON 查询,但我得到 0 个匹配:

GET _search
{
  "query" :{
  "filtered": {
    "query": {
      "match_all": { }
    },
   "filter": {
      "bool" : {
            "must" : [
                {"term" : { "macAddr" : "000A8D810F5A" } },
                {"term" : { "insturmentName" : "Amin's furnace" } },
                {"term" : { "instrumentAddress" : "8D810F5A"}},
                {"term" : { "uhhVersion" :  "v2.5"}},
                {"term" : { "groupName" :  "Amin's Group"}},
                {"term" : { "groupNo" :  2}},
                {"term" : { "instrType" :  60}}
            ]
         }
    }
  }
  }
}

Response:

{
   "took": 3,
   "timed_out": false,
   "_shards": {
      "total": 4,
      "successful": 3,
      "failed": 0
   },
   "hits": {
      "total": 0,
      "max_score": null,
      "hits": []
   }
}

您可以使用带术语过滤器的过滤查询:

{
  "filtered": {
    "query": {
      "match_all": { }
    },
    "filter": {
      "bool" : {
            "must" : [
                {"term" : { "macaddress" : "your_mac" } },
                {"term" : { "another_field" : 123 } }
            ]
         }
    }
  }
}

NEST 版本(将 dynamic 替换为您的响应模型):

var res = esclient.Search<dynamic>(q => q
            .Query(fq => fq
                .Filtered(fqq => fqq
                    .Query(qq => qq.MatchAll())
                    .Filter(ff => ff
                        .Bool(b => b
                            .Must(m1 => m1.Term("macaddress", "your_mac"))
                            .Must(m2 => m2.Term("another_field", 123))
                        )
                    )
                )
            )
        );

根据提供的映射和响应进行更新:

首先需要注意以下几点:

  • 当我们需要索引和搜索关键字或 ID 时,我们使用 term。在你的情况下它是 "macAddr" 但问题是你使用标准分析器对其进行索引(因此 000A8D810F5A 将转换为 000a8d810f5a),并使用 term 搜索它(这将保留按原样传递数据 ==> 000A8D810F5A),那么它永远不会匹配索引数据:000a8d810f5a。 您可以在搜索之前将术语小写或使用 match 查询来解决它。对于案例 "instrumentAddress" 和 "uhhVersion" 可能相同(我不确定,因为我没有样本数据)。

  • 对于案例 "insturmentName"、"groupName",您正在使用标准分析器为 短语 编制索引。因此,像 "Amin's furnace" 这样的数据将被索引为两个术语 amin'sfurnace 和 none,其中 none 匹配传递的术语 Amin's furnace。 在这种情况下,我们可以使用 match 查询来搜索(如果您需要更多选项,则可以使用 query_string

所以快速修复看起来像这样:

GET _search
{
"query" :{
  "filtered": {
     "query": {
        "match_all": { }
      },
     "filter": {
       "bool" : {
        "must" : [
            {"match" : { "macAddr" : "000A8D810F5A" } },
            {"match" : { "insturmentName" : "Amin's furnace" } },
            {"match" : { "instrumentAddress" : "8D810F5A"}},
            {"term" : { "uhhVersion" :  "v2.5"}},
            {"match" : { "groupName" :  "Amin's Group"}},
            {"term" : { "groupNo" :  2}},
            {"term" : { "instrType" :  60}}
          ]
        }
       }
      }
     }
   }

如果您可以将 "macAddr"、"instrumentAddress" 的搜索字词小写,那么您可以将其匹配查询替换为字词查询以获得更好的性能。