【问题标题】:how to match with multiple inputs elasticearch如何匹配多个输入elasticsearch
【发布时间】:2020-05-25 13:13:50
【问题描述】:

我正在尝试使用 terms 使用以下查询查询 3 个环境(开发、测试、产品)上所有可能的日志:尝试使用 mustshould

curl -vs -o -X POST http://localhost:9200/*/_search?pretty=true -d '
{
    "query": {
        "bool": {
           "minimum_should_match": 1,
           "should": {
                "terms": {
                    "can.deployment": ["can-prod", "can-test", "can-dev"]
                }
            "filter": [{
                    "range": {
                        "@timestamp": {
                            "gte": "2020-05-02T17:22:29.069Z",
                            "lt": "2020-05-23T17:23:29.069Z"
                        }
                    }
            }, {
                    "terms": {
                        "can.level": ["WARN", "ERROR"]
                    }
            }, {
                    "terms": {
                        "can.class": ["MTMessage", "ParserService", "JsonParser"]
                    }
            }]
        }
    }
}'

给予:

{
  "took" : 871,
  "timed_out" : false,
  "_shards" : {
    "total" : 391,
    "successful" : 389,
    "failed" : 0
  },
  "hits" : {
    "total" : 0,
    "max_score" : null,
    "hits" : [ ]
  }
}

但是,如果我将 terms 替换为 match,它就可以工作。但无法使用其他输入进行查询,例如查询 WARN 消息、与 ParserService 类相关的查询日志等:

curl -vs -o -X POST http://localhost:9200/*/_search?pretty=true -d '
  {
    "query": {
        "bool": {
            "should": 
                [{"match": {"can.deployment": "can-prod"}}],
            "filter": [{
                    "range": {
                        "@timestamp": {
                            "gte": "2020-03-20T17:22:29.069Z",
                            "lt": "2020-05-01T17:23:29.069Z"
                        }
                    }
            },{
                    "match": {
                        "can.level": "ERROR"
                    }
            },{
                    "match": {
                        "can.class": "MTMessage"
                    }
            }
        ]
        }
    }
  }'

无论有没有条款/匹配,我如何做到这一点。 试过这个,没有运气。我得到 0 个搜索结果:

                    "match": {
                        "can.level": "ERROR"
                    }
            },{
                    "match": {
                        "can.level": "WARN"
                    }
            },{
                    "match": {
                        "can.class": "MTMessage"
                    }
            }

任何提示肯定会有所帮助。蒂亚!

[编辑] 添加映射(/_mapping?pretty=true):

          "can" : {
            "properties" : {
              "class" : {
                "type" : "text",
                "fields" : {
                  "keyword" : {
                    "type" : "keyword",
                    "ignore_above" : 256
                  }
                }
              },
              "deployment" : {
                "type" : "text",
                "fields" : {
                  "keyword" : {
                    "type" : "keyword",
                    "ignore_above" : 256
                  }
                }
              },
              "level" : {
                "type" : "text",
                "fields" : {
                  "keyword" : {
                    "type" : "keyword",
                    "ignore_above" : 256
                  }
                }
              },

添加示例文档:

{
  "took" : 50,
  "timed_out" : false,
  "_shards" : {
    "total" : 391,
    "successful" : 387,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 5.44714,
    "hits" : [
      {
        "_index" : "filebeat-6.1.2-2020.05.21",
        "_type" : "doc",
        "_id" : "AXI9K_cggA4T9jvjZc03",
        "_score" : 5.44714,
        "_source" : {
          "@timestamp" : "2020-05-21T02:59:25.373Z",
          "offset" : 34395681,
          "beat" : {
            "hostname" : "4c80d1588455-661e-7054-a4e5-73c821d7",
            "name" : "4c80d1588455-661e-7054-a4e5-73c821d7",
            "version" : "6.1.2"
          },
          "prospector" : {
            "type" : "log"
          },
          "source" : "/var/logs/packages/gateway_mt/1a27957180c2b57a53e76dd686a06f4983bf233f/logs/gateway_mt.log",
          "message" : "[2020-05-21 02:59:25.373] ERROR can_gateway_mt [ActiveMT SNAP Worker 18253] --- ClientIdAuthenticationFilter: Cannot authorize publishing from client ThingPayload_4
325334a89c9 : not authorized",
          "fileset" : {
            "module" : "can",
            "name" : "services"
          },
          "fields" : { },
          "can" : {
            "component" : "can_gateway_mt",
            "instancename" : "canservices/0",
            "level" : "ERROR",
            "thread" : "ActiveMT SNAP Worker 18253",
            "message" : "Cannot authorize publishing from client ThingPayload_4325334a89c9 : not authorized",
            "class" : "ClientIdAuthenticationFilter",
            "timestamp" : "2020-05-21 02:59:25.373",
            "deployment" : "can-prod"
          }
        }
      }
    ]
  }
}

预期输出: 试图获得与条件匹配的整个文档的转储。类似于上面的示例文档。

【问题讨论】:

  • 你能分享你的映射、示例文档和预期输出吗?
  • 按照建议添加了详细信息。
  • @james,我提供了这两种方法,如果你能仔细阅读它们并提供反馈,那就太好了。

标签: elasticsearch elasticsearch-dsl


【解决方案1】:
"query": {
        "bool": {
           "minimum_should_match": 1,
           "should": {
                "terms": {
                    "can.deployment": ["can-prod", "can-test", "can-dev"]
                }
            "filter": [{
                    "range": {
                        "@timestamp": {
                            "gte": "2020-05-02T17:22:29.069Z",
                            "lt": "2020-05-23T17:23:29.069Z"
                        }
                    }
            }, {
                    "terms": {
                        "can.level": ["WARN", "ERROR"]
                    }
            }, {
                    "terms": {
                        "can.class": ["MTMessage", "ParserService", "JsonParser"]
                    }
            }]
        }
    }

我想,上面的搜索查询不起作用,因为您的字段 can.deployementcan.levelcan.classtext 字段。如果这些是文本字段,Elasticsearch 通过默认标准分析器分析这些类型的字段,它将文本除以停用词并将所有文本转换为小写。您可以通过here 了解更多信息。

对于您的情况,例如 can.deployement 字段值 can-prod 将被分析为

{
    "tokens": [
        {
            "token": "can",
            "start_offset": 0,
            "end_offset": 3,
            "type": "<ALPHANUM>",
            "position": 0
        },
        {
            "token": "prod",
            "start_offset": 4,
            "end_offset": 8,
            "type": "<ALPHANUM>",
            "position": 1
        }
    ]
}

Terms 查询匹配精确的单词(区分大小写的搜索),但是由于 elasticsearch 会分析您的文本并划分并转换为小写,因此您无法找到精确的搜索文本。

为了解决这个问题,在为这 3 个字段(can.deployementcan.levelcan.class)创建索引映射时,您可以创建一个 keyword 类型的字段,它基本上表示 Elasticsearch不分析该字段并按原样存储。

您可以为这 3 个字段创建映射,例如:

映射:

 "mappings": {
            "properties": {
                "can.class": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword"
                        }
                    }
                },
                "can.deployment": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword"
                        }
                    }
                },
                "can.level": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword"
                        }
                    }
                }
            }
        }
    }

现在您可以使用这些关键字字段执行terms 搜索:

搜索查询:

{ "query": {
        "bool": {
           "minimum_should_match": 1,
           "should": {
                "terms": {
                    "can.deployment.keyword": ["can-prod", "can-test", "can-dev"]
                }
           },
            "filter": [ {
                    "terms": {
                        "can.level.keyword": ["WARN", "ERROR"]
                    }
            }, {
                    "terms": {
                        "can.class.keyword": ["MTMessage", "ParserService", "JsonParser"]
                    }
            }]
        }
    }
}

这样,术语查询仅适用于区分大小写的搜索。您可以从here 了解更多相关信息。

【讨论】:

  • @Preena Gupta,谢谢你的回答! ["can-prod", "can-test", "can-dev"] 提供来自 "can-dev" 的日志,而不是来自 "can-prod", "can-test" 的日志。但过滤器术语似乎按预期工作。你知道如何解决这个问题吗?
  • 在您的文档中,can.deployment 的值也是“can-prod”和“can-test”,但文档值不匹配。是否完全匹配?
  • 如果我使用单个术语 "can.deployment.keyword": ["can-test"](或)"can.deployment.keyword": ["can-dev"](使用单独的 curl 命令)运行 curl 命令,它会提供匹配的文档。
  • 不确定。我刚刚用我的测试文档进行了测试,效果很好。您能否粘贴未在结果中获取的相同文档。
  • 文档已发布在问题上(示例文档)。测试、开发和生产都是一样的。只是部署名称因日志源而异。做单独的卷曲工作,所以我想那会做。谢谢!
【解决方案2】:

如果你想做不区分大小写的搜索,你可以使用match 查询来做同样的事情:

搜索查询:

{
    "query": {
        "bool": {

            "must": [
                {
                    "match": {
                        "level": "warn error"
                    }
                },
                {
                    "match": {
                        "class": "MTMessage ParserService JsonParser"
                    }
                },
                {
                    "match": {
                        "deployment": "can-test can-prod can-dev"
                    }
                }

            ]
        }
    }
}

这是因为 Elasticsearch 默认使用与索引分析器相同的分析器分析您的 match 查询文本。由于在您的情况下它是标准分析器,它会将这个 match 查询文本转换为小写并删除停用词。您可以从here 了解更多信息。

例如对于搜索值MTMessage ParserService JsonParser,它将在内部被分析为:

{
    "tokens": [
        {
            "token": "mtmessage",
            "start_offset": 0,
            "end_offset": 9,
            "type": "<ALPHANUM>",
            "position": 0
        },
        {
            "token": "parserservice",
            "start_offset": 10,
            "end_offset": 23,
            "type": "<ALPHANUM>",
            "position": 1
        },
        {
            "token": "jsonparser",
            "start_offset": 24,
            "end_offset": 34,
            "type": "<ALPHANUM>",
            "position": 2
        }
    ]
}

并且由于您的具有此字段的文档值也以这种方式进行了分析,因此它们将匹配。

这个值can-test can-prod can-dev有一个问题,它将被分析为:

{
    "tokens": [
        {
            "token": "can",
            "start_offset": 0,
            "end_offset": 3,
            "type": "<ALPHANUM>",
            "position": 0
        },
        {
            "token": "test",
            "start_offset": 4,
            "end_offset": 8,
            "type": "<ALPHANUM>",
            "position": 1
        },
        {
            "token": "can",
            "start_offset": 9,
            "end_offset": 12,
            "type": "<ALPHANUM>",
            "position": 2
        },
        {
            "token": "prod",
            "start_offset": 13,
            "end_offset": 17,
            "type": "<ALPHANUM>",
            "position": 3
        },
        {
            "token": "can",
            "start_offset": 18,
            "end_offset": 21,
            "type": "<ALPHANUM>",
            "position": 4
        },
        {
            "token": "dev",
            "start_offset": 22,
            "end_offset": 25,
            "type": "<ALPHANUM>",
            "position": 5
        }
    ]
}

现在,如果您的索引中有这种文档:

{
    "can.deployment": "can",
    "can.level": "WARN",
    "can.class": "JsonParser"

}

那么这个文档也会出现在你的搜索结果中。

因此,根据您要执行的搜索类型以及您拥有的搜索数据类型,您可以决定是使用terms 查询还是match 查询。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多