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's
、furnace
和 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" 的搜索字词小写,那么您可以将其匹配查询替换为字词查询以获得更好的性能。
我需要一种方法来使用 "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's
、furnace
和 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" 的搜索字词小写,那么您可以将其匹配查询替换为字词查询以获得更好的性能。