使用 Elasticsearch 搜索精确短语
Search for exact phrase with Elasticsearch
我目前正在开始使用 Elasticsearch。我已经索引了一些 EDIFACT 消息(一种史前数据格式;-)
内容看起来像这样:
UNB+UNOA:2+SENDER+RECEIVER+170509:0050+152538'
UNH+66304+CODECO:D:95B:UN:ITG12'
BGM+34+INGATE OF UCN ABCD+9'
当我搜索短语 UNH+66304+CODECO:D:95B 时,它应该只会 return 一次命中,但它似乎正在 returning 包含其中任何一个的所有文件单词(UNH 在每一份文件中)。
我的查询是这样的:
curl -XGET --netrc-file ~/curl_user 'localhost:9200/edi/message/_search?pretty' -H 'Content-Type: application/json' -d'
{
"query":{
"match":{"MESSAGE":"UNH+66304+CODECO:D:95B"}
}
}'
我试过像这样添加 "and" 运算符:
"match":{
"MESSAGE":{
"query":"UNH+66304+CODECO",
"operator": "and"
}
}
但是 return 没有结果。
我已阅读此处的建议:Searching for exact phrase
我需要使用双引号。 "query":"'UNH+66304+CODECO'" 和 "query":"\"UNH+66304+CODECO\"" 我都试过了,但没什么区别。
我也试过了match_phrase
"match_phrase":{
"MESSAGE":{
"query":"UNH+66304+CODECO"
}
}
没有 return 结果 while
"match_phrase":{
"MESSAGE":{
"query":"UNH+66304"
}
}
确实如此。
对于普通文本,它似乎可以工作,但 Elasticsearch 不喜欢搜索字符串中的 +: 等(不幸的是,它是 EDIFACT 的一部分)。
How to make query_string search exact phrase in ElasticSearch 谈论如果你想要完全匹配使用不同的分析器?
更新: abhishek mishra 确认分析器可能是最佳选择。我使用的是 Elasticsearch 5.4,有很多分析器可供选择:https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-analyzers.html
关键字分析器可能会映射到 abhishek 建议的 'not analysed',因为它是一个 noop 分析器。但是我有点担心使用它,因为消息可能会很长。对搜索的性能有何影响?如果我使用关键字分析器,我还能搜索整封邮件的部分内容吗?
我想知道模式分析器是否适合?
EDIFACT 消息由以 3 个大写字符开头的段组成,并以 ' 结尾(但您可以通过在其前面加上 ? 来转义 ')
FTX+AAA++It?'s a strange data format'
FTX+AAA++Yes it is'
所以上面的例子是两个片段。如果我使用一种模式来分隔这些片段,那会是一个很好的匹配吗?
唯一的问题是目前 MESSAGE 字段可以包含 EDIFACT 消息和 XML 消息。我想使用相同的模式分析器是行不通的,所以我必须根据 MESSAGE 字段的内容创建两种不同的类型(其余的都是一样的)。
第二次更新:
我已按照建议查看分析器。我认为关键字分析器可能不是一个好主意,因为文本可能很长。我发现模式分析器(没有任何自定义模式)工作得很好。它在 : 和 + 上拆分所有内容。搜索类似
{
"query":{
"match_phrase":{"MESSAGE":"RFF+ABT:ATB150538080520172452"}
}
}
或
{
"query":{
"match_phrase":{"MESSAGE":"RFF+ABT:ATB150538080520172452"}
}
}
现在工作。之前的问题是,例如被分成 [rff,abt:atb150538080520172452].
我认为你有 "query" 和 "match_phrase" 反转:
你能这样试试吗:
{
"query": {
"match_phrase": {
"MESSAGE": "UNH+66304"
}
}
}
您对分析仪的看法是正确的。如果查看类型映射,属性 MESSAGE
可能标记为 analyzed
。这就是为什么在索引时它会摆脱特殊字符。您需要将其标记为 not_analyzed
.
如果您告诉我们您的类型映射是什么样的,我可以帮助您进行正确的设置。
例子之一-
如果你的 ES 版本 < 5.0 并且你的类型映射看起来与此类似 -
{
"MESSAGE": {
"type" "string",
"index": "analyzed"
}
}
改为
{
"MESSAGE": {
"type" "string",
"index": "not_analyzed"
}
}
解决方案是使用模式分析器。无需进一步配置(未指定自定义模式),它会将 EDIFACT 消息分解为 non-word/number 个字符。
标准分析器的问题在于它与“:”的行为很奇怪。
所以如果你例如有 RFF+ATB:AB12345;它把它分解成 [rff, atb:ab12345] 所以搜索 ab12345 没有 return 任何东西。
您可以使用
测试分析器或分词器的工作方式
curl -XPOST --netrc-file ~/curl_user 'localhost:9200/_analyze?pretty' -H 'Content-Type: application/json' -d'
{
"analyzer": "standard",
"text": "UNB+UNOA:2+SENDER+RECEIVER+170513:0452+129910165"
}'
如果您只想测试所使用的分词器,可以将 'analyzer' 替换为分词器。
我目前正在开始使用 Elasticsearch。我已经索引了一些 EDIFACT 消息(一种史前数据格式;-) 内容看起来像这样:
UNB+UNOA:2+SENDER+RECEIVER+170509:0050+152538'
UNH+66304+CODECO:D:95B:UN:ITG12'
BGM+34+INGATE OF UCN ABCD+9'
当我搜索短语 UNH+66304+CODECO:D:95B 时,它应该只会 return 一次命中,但它似乎正在 returning 包含其中任何一个的所有文件单词(UNH 在每一份文件中)。 我的查询是这样的:
curl -XGET --netrc-file ~/curl_user 'localhost:9200/edi/message/_search?pretty' -H 'Content-Type: application/json' -d'
{
"query":{
"match":{"MESSAGE":"UNH+66304+CODECO:D:95B"}
}
}'
我试过像这样添加 "and" 运算符:
"match":{
"MESSAGE":{
"query":"UNH+66304+CODECO",
"operator": "and"
}
}
但是 return 没有结果。 我已阅读此处的建议:Searching for exact phrase 我需要使用双引号。 "query":"'UNH+66304+CODECO'" 和 "query":"\"UNH+66304+CODECO\"" 我都试过了,但没什么区别。
我也试过了match_phrase
"match_phrase":{
"MESSAGE":{
"query":"UNH+66304+CODECO"
}
}
没有 return 结果 while
"match_phrase":{
"MESSAGE":{
"query":"UNH+66304"
}
}
确实如此。 对于普通文本,它似乎可以工作,但 Elasticsearch 不喜欢搜索字符串中的 +: 等(不幸的是,它是 EDIFACT 的一部分)。
How to make query_string search exact phrase in ElasticSearch 谈论如果你想要完全匹配使用不同的分析器?
更新: abhishek mishra 确认分析器可能是最佳选择。我使用的是 Elasticsearch 5.4,有很多分析器可供选择:https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-analyzers.html
关键字分析器可能会映射到 abhishek 建议的 'not analysed',因为它是一个 noop 分析器。但是我有点担心使用它,因为消息可能会很长。对搜索的性能有何影响?如果我使用关键字分析器,我还能搜索整封邮件的部分内容吗?
我想知道模式分析器是否适合? EDIFACT 消息由以 3 个大写字符开头的段组成,并以 ' 结尾(但您可以通过在其前面加上 ? 来转义 ')
FTX+AAA++It?'s a strange data format'
FTX+AAA++Yes it is'
所以上面的例子是两个片段。如果我使用一种模式来分隔这些片段,那会是一个很好的匹配吗?
唯一的问题是目前 MESSAGE 字段可以包含 EDIFACT 消息和 XML 消息。我想使用相同的模式分析器是行不通的,所以我必须根据 MESSAGE 字段的内容创建两种不同的类型(其余的都是一样的)。
第二次更新: 我已按照建议查看分析器。我认为关键字分析器可能不是一个好主意,因为文本可能很长。我发现模式分析器(没有任何自定义模式)工作得很好。它在 : 和 + 上拆分所有内容。搜索类似
{
"query":{
"match_phrase":{"MESSAGE":"RFF+ABT:ATB150538080520172452"}
}
}
或
{
"query":{
"match_phrase":{"MESSAGE":"RFF+ABT:ATB150538080520172452"}
}
}
现在工作。之前的问题是,例如被分成 [rff,abt:atb150538080520172452].
我认为你有 "query" 和 "match_phrase" 反转:
你能这样试试吗:
{
"query": {
"match_phrase": {
"MESSAGE": "UNH+66304"
}
}
}
您对分析仪的看法是正确的。如果查看类型映射,属性 MESSAGE
可能标记为 analyzed
。这就是为什么在索引时它会摆脱特殊字符。您需要将其标记为 not_analyzed
.
如果您告诉我们您的类型映射是什么样的,我可以帮助您进行正确的设置。
例子之一-
如果你的 ES 版本 < 5.0 并且你的类型映射看起来与此类似 -
{
"MESSAGE": {
"type" "string",
"index": "analyzed"
}
}
改为
{
"MESSAGE": {
"type" "string",
"index": "not_analyzed"
}
}
解决方案是使用模式分析器。无需进一步配置(未指定自定义模式),它会将 EDIFACT 消息分解为 non-word/number 个字符。
标准分析器的问题在于它与“:”的行为很奇怪。 所以如果你例如有 RFF+ATB:AB12345;它把它分解成 [rff, atb:ab12345] 所以搜索 ab12345 没有 return 任何东西。
您可以使用
测试分析器或分词器的工作方式curl -XPOST --netrc-file ~/curl_user 'localhost:9200/_analyze?pretty' -H 'Content-Type: application/json' -d'
{
"analyzer": "standard",
"text": "UNB+UNOA:2+SENDER+RECEIVER+170513:0452+129910165"
}'
如果您只想测试所使用的分词器,可以将 'analyzer' 替换为分词器。