python - 带有嵌套过滤器的Elasticsearch-dsl以及完全匹配的AND和OR条件

标签 python python-3.x elasticsearch flask elasticsearch-dsl

前端有三个参数:

  • State-字符串
  • Categories-字符串数组。字符串可以包含几个单词。
  • Tags-与类别相似。

  • 所有参数都是可选的。

    如果传输了多个,则需要通过AND(以及statecategorytag的重合)实现它们的 bundle 包。如果提交了多个categoriestags,则至少匹配其中一个。

    也就是说,如果请求到达时带有参数
    {"state": "Alaska", "categories": ["category 1", "category 2"]}
    

    答案将是
  • state = Alaskacategories = category 1;
  • state = Alaska, categories = category 2;
  • state = Alaska, categories = [category 1, category 2];
  • state = Alaska, categories = [category 1, category 3](具有至少一个请求的类别)。

  • 不适合
  • state = Alabama, categories = category 1
  • state = Alaska, categories = 3
  • state = Alaska, categories = 1 category(类别名称应为1合1 "category 1" != "1 category")

  • 为了发送elastikserch,我从python(3.7)发送请求。图书馆
    elasticsearch-dsl

    通过Q对象(在其中使用了match)收集了三个过滤器。
    combined_filter = state_filter & categories_filter & tags_filter
    
    categoriestags的列表分为subfilters through OR
    query = queries.pop()
    for item in queries:
        query |= item
    

    elasticsearch创建了这样的请求。
    Bool(minimum_should_match=1, 
        must=[Match(state='Alaska'), MatchAll()], 
        should=[Match(categories='category 1'), Match(categories='category 2')]
    )
    

    为什么此逻辑查找的条目与category / tag名称不完全相同?
    from typing import List
    
    from elasticsearch import Elasticsearch
    from elasticsearch_dsl import Q, Search
    from flask import request
    from flask.views import MethodView
    
    
    es = Elasticsearch()
    
    
    class ArticleSearchAPIView(MethodView):
        """
        Search articles using ElasticSearch
        """
    
        @staticmethod
        def filter_create(queries: List[Q]) -> Q:
            """
            Creates Q.OR filter
            """
            query = queries.pop()
            for item in queries:
                query |= item
            return query
    
        def get(self) -> dict:
            """
            Search article
            First request - with empty params
            """
            search = Search(using=es, index=ArticleModel.__tablename__)
            state_filter = categories_filter = tags_filter = Q()
            result = "Articles not found."
    
            data = request.get_json()
            categories = data.get("categories")
            tags = data.get("tags")
            state = data.get("state")
    
            if state:
                state_filter = Q("match", state=state)
    
            if categories:
                queries = [Q("match", categories=value) for value in categories]
                categories_filter = self.filter_create(queries)
    
            if tags:
                queries = [Q("match", tags=value) for value in tags]
                tags_filter = self.filter_create(queries)
    
            combined_filter = state_filter & categories_filter & tags_filter
            found = (
                search.filter(combined_filter)
                .execute()
                .to_dict()["hits"]
                .get("hits")
            )
    
            if found:
                result = [article["_source"] for article in found]
            return {"response": result}
    

    更新
    Article and CategoryArticle and Tag之间的关系-MTM
    制图
    {
      "articles": {
        "mappings": {
          "properties": {
            ...
            "categories": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "state": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "tags": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            }
            ...
          }
        }
      }
    }
    

    最佳答案

    您可以使用 bool(boolean) 查询。

    在 bool(boolean) 查询ElasticSearch Boolean Query

    您具有“必须”,它等同于“与”运算符。而“应该”充当“或”运算符。

    {
      "query": {
        "bool" : {
          "must" : {
            "term" : { "user" : "kimchy" }
          },
          "should" : [
            { "term" : { "tag" : "wow" } },
            { "term" : { "tag" : "elasticsearch" } }
          ],
        }
      }
    }

    关于python - 带有嵌套过滤器的Elasticsearch-dsl以及完全匹配的AND和OR条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62434860/

    相关文章:

    python - 为什么 os.system() 不是执行 shell 命令的推荐方式?

    python - YouTube分析

    python - 修改 django 管理用户界面

    python - 如果需要,使用 SQL 或代码从多个 (4) 表连接中获取结果(python)

    elasticsearch - elasticsearch时间戳格式是什么?

    python - 在django测试框架中全局设置?

    python - 如何在 Django 管理中更改 "app name"?

    python-3.x - python asyncio - 如何等待取消的屏蔽任务?

    elasticsearch - Logstash 没有在 ES 上以正确的格式存储数据

    elasticsearch聚合PHP