elasticsearch中的嵌套过滤,具有相同嵌套类型的多个术语

时间:2014-11-03 22:29:42

标签: elasticsearch filter nested aggregation

我是弹性搜索的新手,所以也许我的方法是完全错误的,但我想制作食谱索引并允许用户过滤 down 使用仍在子集中找到的聚合成分。

也许我使用错误的语言来解释所以也许这个例子会澄清。我想搜索术语salt的食谱;这导致三个食谱:

  1. 含有成分:盐,面粉,水
  2. 含有成分:盐,胡椒,鸡蛋
  3. 含有成分:水,面粉,鸡蛋,盐
  4. 结果成分的总量返回盐,面粉,水,胡椒,鸡蛋。当我用flour过滤时,我只希望食谱1和3出现在搜索结果中(成分上的聚合物应该只返回盐,面粉,水,蛋和盐)。当我添加另一个过滤器egg时,我只想要出现配方3(并且聚合物应该只返回水,面粉,鸡蛋,盐)。

    我无法让后者工作:默认查询旁边的一个过滤器 确实 根据需要缩小搜索范围,但在添加其他 术语(egg)对术语过滤结果再次开始包括b,就好像它是一个OR过滤器。然而,将AND添加到过滤器执行会导致无结果......我做错了什么?

    我的映射:

    {
      "recipe": {
        "properties": {
          "title": {
            "analyzer": "dutch",
            "type": "string"
          },
          "ingredients": {
            "type": "nested",
            "properties": {
              "name": {
                "type": "string",
                "analyzer": "dutch",
                "include_in_parent": true,
                "fields": {
                  "raw": {
                    "type": "string",
                    "index": "not_analyzed"
                  }
                }
              }
            }
          }
        }
      }
    }
    

    我的查询:

    {
      "query": {
        "filtered": {
          "query": {
            "bool": {
              "should": [
                {
                  "match": {
                    "_all": "salt"
                  }
                }
              ]
            }
          },
          "filter": {
            "nested": {
              "path": "ingredients",
              "filter": {
                "terms": {
                  "ingredients.name": [
                    "flour",
                    "egg"
                  ],
                  "execution": "and"
                }
              }
            }
          }
        }
      },
      "size": 50,
      "aggregations": {
        "ingredients": {
          "nested": {
            "path": "ingredients"
          },
          "aggregations": {
            "count": {
              "terms": {
                "field": "ingredients.name.raw"
              }
            }
          }
        }
      }
    }
    

1 个答案:

答案 0 :(得分:2)

为什么在这里使用nested映射?其主要目的是保持子对象属性之间的关系,但您的ingredients字段只有一个属性,可以简单地建模为字符串字段。

所以,如果你像这样更新你的映射:

POST recipes
{
  "mappings": {
    "recipe": {
      "properties": {
        "title": {
          "type": "string"
        },
        "ingredients": {
          "name": {
            "type": "string",
            "fields": {
              "raw": {
                "type": "string",
                "index": "not_analyzed"
              }
            }
          }
        }
      }
    }
  }
}

您仍然可以将食谱编入索引:

{
  "title":"recipe b",
  "ingredients":["salt","pepper","egg"]
}

此查询为您提供您正在等待的结果:

POST recipes/recipe/_search
{
  "query": {
    "filtered": {
      "query": {
        "match": {
          "_all": "salt"
        }
      },
      "filter": {
        "terms": {
          "ingredients": [
            "flour",
            "egg"
          ],
          "execution": "and"
        }
      }
    }
  },
  "size": 50,
  "aggregations": {
    "ingredients": {
      "terms": {
        "field": "ingredients"
      }
    }
  }
}

是:

{
   ...
   "hits": {
      "total": 1,
      "max_score": 0.22295055,
      "hits": [
         {
            "_index": "recipes",
            "_type": "recipe",
            "_id": "PP195TTsSOy-5OweArNsvA",
            "_score": 0.22295055,
            "_source": {
               "title": "recipe c",
               "ingredients": [
                  "salt",
                  "flour",
                  "egg",
                  "water"
               ]
            }
         }
      ]
   },
   "aggregations": {
      "ingredients": {
         "buckets": [
            {
               "key": "egg",
               "doc_count": 1
            },
            {
               "key": "flour",
               "doc_count": 1
            },
            {
               "key": "salt",
               "doc_count": 1
            },
            {
               "key": "water",
               "doc_count": 1
            }
         ]
      }
   }
}

希望这有帮助。