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

未知

前端有三个参数:

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

所有参数都是可选的。

如果传输了几个,则需要通过AND(和state,和category,和的巧合)实现它们的捆绑包tag如果提交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

通过对象(在其中使用)收集了三个过滤器Qmatch

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
            }
          }
        }
        ...
      }
    }
  }
}
未知

我决定elasticsearch-dsl在这里不需要使用

这是我做出的决定。

from typing import Dict, List, Tuple, Union

from elasticsearch import Elasticsearch
from flask import request
from flask.views import MethodView

from .models import AticleModel  # ArticleModel.__tablename__ == "articles"


es = Elasticsearch()


class ArticleSearchAPIView(MethodView):
    """
    Search articles using ElasticSearch
    """

    def get(
        self,
    ) -> Union[
        Dict[str, Union[list, List[str]]],
        Tuple[Dict[str, str], int],
        Dict[str, Union[list, str]],
    ]:
        """
        Search articles
        """
        data = request.get_json()
        categories = data.get("categories")
        tags = data.get("tags")
        state = data.get("state")
        result = "Articles not found."

        query = {"bool": {"must": []}}
        if state:
            query["bool"]["must"].append({"term": {"state.keyword": state}})
        if categories:
            query["bool"]["must"].append(
                {"terms": {"categories.keyword": categories}}
            )
        if tags:
            query["bool"]["must"].append({"terms": {"tags.keyword": tags}})

        found = es.search(
            index=ArticleModel.__tablename__, body={"query": query},
        )["hits"].get("hits")

        if found:
            result = [article["_source"] for article in found]
        return {"response": result}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

带有嵌套属性的过滤器和聚合的Elasticsearch DSL python查询

带有范围和存在过滤器的Elasticsearch

带有大写令牌的Elasticsearch word_delimiter过滤器不匹配

拉丁猪:组中的所有对-带有十字架和过滤器的嵌套foreach

具有过滤器匹配的Elasticsearch聚合

VBA - 应用带有部分标题匹配的过滤器

带有替换和搜索功能的熊猫过滤器

带有CIAffineClamp过滤器的MacOS和Swift 3

带有 $match 和 $near 的 Mongoose facet 过滤器

Elasticsearch词组匹配过滤器

Elasticsearch仅与过滤器匹配

合并hunspell过滤器后,elasticSearch中的完全匹配

嵌套属性匹配条件的过滤器列表

如何使用带有ng-repeat的过滤器基于字段值过滤和对象

使用带有多个下拉菜单的 jQuery“查找”和“过滤器”过滤

使用带有嵌套三元运算符和过滤器功能的映射函数在 React Native View 中渲染数据

带有动态过滤器文本框和多列结果的列表框,用于使用过滤器找到的匹配项

Elasticsearch查询中的条件和范围过滤器

Spring Integration DSL过滤器与带有单个收件人和DefaultOutputToParentFlow的RouteToRecipients

jQuery嵌套列表过滤器-当父项匹配时显示所有子项

带有过滤器的搜索栏,以及使用Ionic 2的JSON数据

具有字段优先级的嵌套查询和过滤器查询

ES 7 - 使用带有过滤器的匹配查询

带有过滤器的Get-ChildItem返回匹配但不包含的文件

安全性:过滤器链模式匹配url带有符号“?”

为什么带有计数的过滤器的结果不能直接用作 Swift 3 中的条件

RethinkDB上两个带有OR条件的过滤器

如何在anguarljs中使用带有某些条件的唯一过滤器

带有条件过滤器的MySQL Json提取