elasticsearch如何检索包含已知类型以外的类型的数据

新手上路,请多包涵

问题描述

请教一个es问题,tag字段有三种已知类型java,css,html,一条数据可以包含多个tag;那么如何检索出包含其他未知tag的数据,例如[java,php],[html, javascript]

阅读 1.8k
1 个回答

提供一种纯Elasticsearch的方法,当然已知类型过多的情况下应该就不太适用了。但是算是一种方法吧。就是增加一个tag数量的计数器字段cnt。你描述的场景就可以实现了。
下面是我做的Demo
1、先插入数据

PUT _bulk
{"index": {"_index": "test_index", "_id": "1"}}
{"cnt": 1, "tags": ["java"]}
{"index": {"_index": "test_index", "_id": "2"}}
{"cnt": 1, "tags": ["css"]}
{"index": {"_index": "test_index", "_id": "3"}}
{"cnt": 1, "tags": ["html"]}
{"index": {"_index": "test_index", "_id": "4"}}
{"cnt": 2, "tags": ["java","css"]}
{"index": {"_index": "test_index", "_id": "5"}}
{"cnt": 2, "tags": ["java","html"]}
{"index": {"_index": "test_index", "_id": "6"}}
{"cnt": 2, "tags": ["css","html"]}
{"index": {"_index": "test_index", "_id": "7"}}
{"cnt": 3, "tags": ["java", "css", "html"]}
{"index": {"_index": "test_index", "_id": "8"}}
{"cnt": 2, "tags": ["java","php"]}
{"index": {"_index": "test_index", "_id": "9"}}
{"cnt": 2, "tags": ["html","javascript"]}

2、查询

GET /test_index/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "bool": {
            "must": [
              {
                "term": {
                  "cnt": {
                    "value": 1
                  }
                }
              },
              {
                "match": {
                  "tags": "java"
                }
              }
            ]
          }
        },
        {
          "bool": {
            "must": [
              {
                "term": {
                  "cnt": {
                    "value": 1
                  }
                }
              },
              {
                "match": {
                  "tags": "css"
                }
              }
            ]
          }
        },
        {
          "bool": {
            "must": [
              {
                "term": {
                  "cnt": {
                    "value": 1
                  }
                }
              },
              {
                "match": {
                  "tags": "html"
                }
              }
            ]
          }
        },
        {
          "bool": {
            "must": [
              {
                "term": {
                  "cnt": {
                    "value": 2
                  }
                }
              },
              {
                "match": {
                  "tags": {
                    "query": "java css",
                    "minimum_should_match": 2
                  }
                }
              }
            ]
          }
        },
        {
          "bool": {
            "must": [
              {
                "term": {
                  "cnt": {
                    "value": 2
                  }
                }
              },
              {
                "match": {
                  "tags": {
                    "query": "java html",
                    "minimum_should_match": 2
                  }
                }
              }
            ]
          }
        },
        {
          "bool": {
            "must": [
              {
                "term": {
                  "cnt": {
                    "value": 2
                  }
                }
              },
              {
                "match": {
                  "tags": {
                    "query": "css html",
                    "minimum_should_match": 2
                  }
                }
              }
            ]
          }
        },
        {
          "bool": {
            "must": [
              {
                "term": {
                  "cnt": {
                    "value": 3
                  }
                }
              },
              {
                "match": {
                  "tags": {
                    "query": "java css html",
                    "minimum_should_match": 3
                  }
                }
              }
            ]
          }
        }
      ]
    }
  }
}

结果如下:

{
  "took" : 4,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 0.0,
    "hits" : [
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "8",
        "_score" : 0.0,
        "_source" : {
          "cnt" : 2,
          "tags" : [
            "java",
            "php"
          ]
        }
      },
      {
        "_index" : "test_index",
        "_type" : "_doc",
        "_id" : "9",
        "_score" : 0.0,
        "_source" : {
          "cnt" : 2,
          "tags" : [
            "html",
            "javascript"
          ]
        }
      }
    ]
  }
}

当然这个肯定是不通用的,比如已知类型过多,组合的方式就会变得过多,查询语句就会变得超级复杂。
要做成通用的,可以在逻辑上进行处理,适用scroll遍历数据,然后在逻辑上判断,查出来的tags是否是已知类型集合的子集即可

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进