Elasticsearch:错误的方面结果

时间:2014-02-06 14:01:21

标签: filter elasticsearch facet

我想使用elasticsearch在我的产品列表页面上实现构面过滤器。 基本上我的产品文档索引包含许多产品,其中包含许多变体。

将变体定义为“嵌套”对象,以确保仅在变体与所有过滤条件匹配的情况下返回产品。 过滤变化似乎是正确的。然而,facets结果并不像我期望的一样,可以使用构面过滤器。

例如,我的查询返回了facet“f_attribute_scent”的术语“东方”和“柑橘”。但是我只想找回与我的过滤器匹配的术语,即“柑橘”。

我已尝试使用facet过滤器和其他所有内容,但我无法让它正常工作。

我的映射如下所示:

curl -XPOST localhost:9200/products -d '
{
   "mappings": {
      "de": {
         "properties": {
            "variants": {
               "type": "nested",
               "include_in_parent": true
            }
         }
      }
   }
}
'

这是我的测试数据:

curl -XPUT localhost:9200/products/de/12 -d '
{
    "id": "12",
    "categories": [
        {
            "id": "12345",
            "sort": "1"
        },
        {
            "id": "23456",
            "sort": "2"
        },
        {
            "id": "34567",
            "sort": "3"
        }
    ],
    "variants": [
        {
            "id": "12.1.1",
            "brand": "guerlain",
            "collection": "emporio",
            "rating": 4,
            "color": "green",
            "price": 31,
            "scent": "fruity"
        },
        {
            "id": "12.1.2",
            "brand": "guerlain",
            "collection": "emporio",
            "rating": 2,
            "color": "blue",
            "price": 49.99,
            "scent": "flowery"

        }
    ]
}'

curl -XPUT localhost:9200/products/de/15 -d '
{
    "id": "15",
    "categories": [
        {
            "id": "12345",
            "sort": "1"
        },
        {
            "id": "23456",
            "sort": "2"
        },
        {
            "id": "34567",
            "sort": "3"
        }
    ],
    "variants": [
        {
            "id": "15.1.1",
            "brand": "dior",
            "collection": "foobar",
            "rating": 4,
            "color": "green",
            "price": 48.00,
            "scent": "oriental"
        },
        {
            "id": "15.1.2",
            "brand": "dior",
            "collection": "foobar",
            "rating": 2,
            "color": "red",
            "price": 52,
            "scent": "citrus"
        }
    ]
}'

这是查询:

curl -XGET localhost:9200/products/de/_search
{
   "query": {
      "filtered": {
         "query": {
            "match_all": {}
         },
         "filter": {
            "nested": {
               "path": "variants",
               "filter": {
                  "bool": {
                     "must": [
                        {
                           "terms": {
                              "variants.color": [
                                 "green",
                                 "red"
                              ]
                           }
                        },
                        {
                           "term": {
                              "variants.scent": "citrus"
                           }
                        }
                     ]
                  }
               }
            }
         }
      }
   },
   "facets": {
      "f_attribute_color": {
         "terms": {
            "all_terms": true,
            "field": "variants.color"
         }
      },
      "f_attribute_scent": {
         "terms": {
            "field": "variants.scent"
         }
      }
   }
}

......结果:

{
   "took": 2,
   "timed_out": false,
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "hits": {
      "total": 1,
      "max_score": 1,
      "hits": [
         {
            "_index": "products",
            "_type": "de",
            "_id": "15",
            "_score": 1,
            "_source": {
               "id": "15",
               "categories": [
                  {
                     "id": "12345",
                     "sort": "1"
                  },
                  {
                     "id": "23456",
                     "sort": "2"
                  },
                  {
                     "id": "34567",
                     "sort": "3"
                  }
               ],
               "variants": [
                  {
                     "id": "15.1.1",
                     "brand": "dior",
                     "collection": "foobar",
                     "rating": 4,
                     "color": "green",
                     "price": 48,
                     "scent": "oriental"
                  },
                  {
                     "id": "15.1.2",
                     "brand": "dior",
                     "collection": "foobar",
                     "rating": 2,
                     "color": "red",
                     "price": 52,
                     "scent": "citrus"
                  }
               ]
            }
         }
      ]
   },
   "facets": {
      "f_attribute_color": {
         "_type": "terms",
         "missing": 0,
         "total": 2,
         "other": 0,
         "terms": [
            {
               "term": "red",
               "count": 1
            },
            {
               "term": "green",
               "count": 1
            }
         ]
      },
      "f_attribute_scent": {
         "_type": "terms",
         "missing": 0,
         "total": 2,
         "other": 0,
         "terms": [
            {
               "term": "oriental",
               "count": 1
            },
            {
               "term": "citrus",
               "count": 1
            }
         ]
      }
   }
}

3 个答案:

答案 0 :(得分:1)

根据您正在编制索引的上述数据示例,您会看到citrusoriental作为术语方面的结果,因为您的文档有variants作为数组以及这两个术语对于与您的查询匹配的文档有效。

来自Elasticsearch Facets Documentation

  

要记住一个重要的区别。虽然搜索查询限制了返回的文档和构面计数,但搜索过滤器仅限制返回的文档 - 但不限制构面计数。

     

如果您需要限制文档和构面,并且您不愿意或无法使用查询,则可以使用构面过滤器。

根据您要求的文档和所需结果,您可能需要考虑使用Filter Facet

答案 1 :(得分:1)

您的嵌套文档有两种方式编制索引:

  1. 作为独立文档,variants数组中每个元素一个,
  2. 顶级de文档中的
  3. ,就好像您已将variants字段设置为object类型
  4. 上述(2)的原因是您将include_in_parent设置为true。实际上,顶级文档看起来像:

    {
        "id": "12",
        "variants.id":    [ "12.1.1","12.1.2"],
        "variants.brand": [ "guerlain", "guerlain"],
        "variants.color": [ "green", "blue"]
        ... etc ...
    }
    

    您的查询正确使用了nested过滤器,该过滤器标识了匹配的顶级文档,但是您可以在顶级文档上进行操作,而不是嵌套文档,这就是您获得所有结果的原因

    要解决此问题,您需要做的就是更改您的方面以改为使用嵌套文档 将您在主查询中使用的相同嵌套过滤器添加为facet_filter

    "facets": {
      "f_attribute_color": {
         "terms": {
            "field": "variants.color"
         },
         "nested": "variants",
         "facet_filter": {
            "bool": {
               "must": [
                  {
                     "terms": {
                        "variants.color": [
                           "green",
                           "red"
                        ]
                     }
                  },
                  {
                     "term": {
                        "variants.scent": "citrus"
                     }
                  }
               ]
            }
         }
      },
      "f_attribute_scent": {
         "terms": {
            "field": "variants.scent"
         },
         "nested": "variants",
         "facet_filter": {
            "bool": {
               "must": [
                  {
                     "terms": {
                        "variants.color": [
                           "green",
                           "red"
                        ]
                     }
                  },
                  {
                     "term": {
                        "variants.scent": "citrus"
                     }
                  }
               ]
            }
         }
      }
    }
    

答案 2 :(得分:0)

你是对的:如果我使用你的过滤器面,我只会被退回"柑橘"为了"香味"小面。

但是,如果我想按品牌名称过滤" dior"我又遇到了同样的问题。方面结果返回" dior"计数为" 2"。原因是现在两种变体都有相同的品牌名称:

GET /products/de/_search
{
   "filter": {
      "nested": {
         "path": "variants",
         "filter": {
            "bool": {
               "must": [
                  {
                     "term": {
                        "variants.brand": "dior"
                     }
                  }
               ]
            }
         }
      }
   },
   "facets": {
      "f_attribute_brand": {
         "nested": "variants",
         "facet_filter": {
            "bool": {
               "must": [
                  {
                     "term": {
                        "variants.brand": "dior"
                     }
                  }
               ]
            }
         },
         "terms": {
            "field": "variants.brand"
         }
      }
   }
}

结果:

{
   "took": 3,
   "timed_out": false,
   "_shards": {
      "total": 5,
      "successful": 5,
      "failed": 0
   },
   "hits": {
      "total": 1,
      "max_score": 1,
      "hits": [
         {
            "_index": "products",
            "_type": "de",
            "_id": "15",
            "_score": 1
         }
      ]
   },
   "facets": {
      "f_attribute_brand": {
         "_type": "terms",
         "missing": 0,
         "total": 2,
         "other": 0,
         "terms": [
            {
               "term": "dior",
               "count": 2
            }
         ]
      }
   }
}