Elasticsearch:在分面时排除过滤器可能吗? (就像在 Solr 中一样)

发布于 2024-12-27 09:52:02 字数 564 浏览 0 评论 0原文

我正在考虑从 Solr 更改为 ES。 我找不到相关信息的一件事是 ES 是否允许我在分面时定义排除过滤器。

例如,考虑 producttype 的值:A,B,C,我想对其进行分面(即:显示计数)。另请考虑查询仅限于 producttype: A

在这种情况下,Solr 允许我指定要排除约束 producttype: A 来影响 producttype 上的分面。 IOW,它显示 producttype 上的计数,就好像尚未应用约束 producttype: A 一样。

如何在 Solr 中执行此操作,请参阅:http://wiki.apache.org/solr/SimpleFacetParameters >标记和排除过滤器

在 ElasticSearch 中有什么方法可以做到这一点?

I'm looking into changing from Solr to ES.
One of the things I can't find info about is whether ES lets me define exclusion filters when faceting.

For example consider producttype with values: A,B,C which I want to facet on (i.e: show counts for). Also consider that the query is constrained to producttype: A.

In this case Solr allows me to specify that I want to exclude the contraint producttype: A from impacting faceting on producttype. IOW, it displays counts on producttype as if the constraint producttype: A has not been applied.

How to do this in Solr see: http://wiki.apache.org/solr/SimpleFacetParameters > Tagging and excluding Filters

Is there any way to do this in ElasticSearch?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

就像说晚安 2025-01-03 09:52:02

是的,你可以。

虽然您可以在查询 DSL 中使用过滤器,但搜索 API 还接受顶级 filter 参数,该参数用于在计算 Facet 后过滤搜索结果。

例如:

1) 首先,创建索引,并且由于您希望将 product_type 视为枚举,因此将其设置为 not_analyzed

curl -XPUT 'http://127.0.0.1:9200/my_index/?pretty=1'  -d '
{
   "mappings" : {
      "product" : {
         "properties" : {
            "product_type" : {
               "index" : "not_analyzed",
               "type" : "string"
            },
            "product_name" : {
               "type" : "string"
            }
         }
      }
   }
}
'

2) 索引一些文档(注意,文档 3 有不同的 product_name):

curl -XPUT 'http://127.0.0.1:9200/my_index/product/1?pretty=1'  -d '
{
   "product_type" : "A",
   "product_name" : "foo bar"
}
'
curl -XPUT 'http://127.0.0.1:9200/my_index/product/2?pretty=1'  -d '
{
   "product_type" : "B",
   "product_name" : "foo bar"
}
'
curl -XPUT 'http://127.0.0.1:9200/my_index/product/3?pretty=1'  -d '
{
   "product_type" : "C",
   "product_name" : "bar"
}
'

3) 搜索名称包含 foo 的产品(不包括文档 3,因此不包括 product_type C),计算 product_name 中包含 foo 的所有文档的 product_type 的构面,然后过滤搜索结果by product_type == A:

curl -XGET 'http://127.0.0.1:9200/my_index/product/_search?pretty=1'  -d '
{
   "query" : {
      "text" : {
         "product_name" : "foo"
      }
   },
   "filter" : {
      "term" : {
         "product_type" : "A"
      }
   },
   "facets" : {
      "product_type" : {
         "terms" : {
            "field" : "product_type"
         }
      }
   }
}
'

# {
#    "hits" : {
#       "hits" : [
#          {
#             "_source" : {
#                "product_type" : "A",
#                "product_name" : "foo bar"
#             },
#             "_score" : 0.19178301,
#             "_index" : "my_index",
#             "_id" : "1",
#             "_type" : "product"
#          }
#       ],
#       "max_score" : 0.19178301,
#       "total" : 1
#    },
#    "timed_out" : false,
#    "_shards" : {
#       "failed" : 0,
#       "successful" : 5,
#       "total" : 5
#    },
#    "facets" : {
#       "product_type" : {
#          "other" : 0,
#          "terms" : [
#             {
#                "count" : 1,
#                "term" : "B"
#             },
#             {
#                "count" : 1,
#                "term" : "A"
#             }
#          ],
#          "missing" : 0,
#          "_type" : "terms",
#          "total" : 2
#       }
#    },
#    "took" : 3
# }

4) 在 product_name 中搜索 foo,但计算所有的构面索引中的产品,通过指定global 参数:

# [Wed Jan 18 17:15:09 2012] Protocol: http, Server: 192.168.5.10:9200
curl -XGET 'http://127.0.0.1:9200/my_index/product/_search?pretty=1'  -d '
{
   "query" : {
      "text" : {
         "product_name" : "foo"
      }
   },
   "filter" : {
      "term" : {
         "product_type" : "A"
      }
   },
   "facets" : {
      "product_type" : {
         "global" : 1,
         "terms" : {
            "field" : "product_type"
         }
      }
   }
}
'

# [Wed Jan 18 17:15:09 2012] Response:
# {
#    "hits" : {
#       "hits" : [
#          {
#             "_source" : {
#                "product_type" : "A",
#                "product_name" : "foo bar"
#             },
#             "_score" : 0.19178301,
#             "_index" : "my_index",
#             "_id" : "1",
#             "_type" : "product"
#          }
#       ],
#       "max_score" : 0.19178301,
#       "total" : 1
#    },
#    "timed_out" : false,
#    "_shards" : {
#       "failed" : 0,
#       "successful" : 5,
#       "total" : 5
#    },
#    "facets" : {
#       "product_type" : {
#          "other" : 0,
#          "terms" : [
#             {
#                "count" : 1,
#                "term" : "C"
#             },
#             {
#                "count" : 1,
#                "term" : "B"
#             },
#             {
#                "count" : 1,
#                "term" : "A"
#             }
#          ],
#          "missing" : 0,
#          "_type" : "terms",
#          "total" : 3
#       }
#    },
#    "took" : 4
# }

更新以回答来自OP的扩展问题:

您还可以将过滤器直接应用于每个方面 - 这些称为facet_filters

与之前的示例类似:

1) 创建索引:

curl -XPUT 'http://127.0.0.1:9200/my_index/?pretty=1'  -d '
{
   "mappings" : {
      "product" : {
         "properties" : {
            "color" : {
               "index" : "not_analyzed",
               "type" : "string"
            },
            "name" : {
               "type" : "string"
            },
            "type" : {
               "index" : "not_analyzed",
               "type" : "string"
            }
         }
      }
   }
}
'

2) 索引一些数据:

curl -XPUT 'http://127.0.0.1:9200/my_index/product/1?pretty=1'  -d '
{
   "color" : "red",
   "name" : "foo bar",
   "type" : "A"
}
'

curl -XPUT 'http://127.0.0.1:9200/my_index/product/2?pretty=1'  -d '
{
   "color" : [
      "red",
      "blue"
   ],
   "name" : "foo bar",
   "type" : "B"
}
'

curl -XPUT 'http://127.0.0.1:9200/my_index/product/3?pretty=1'  -d '
{
   "color" : [
      "green",
      "blue"
   ],
   "name" : "bar",
   "type" : "C"
}
'

3) 搜索、过滤同时具有 type==Acolor 的产品 == blue,然后对除“其他”过滤器之外的每个属性运行构面:

curl -XGET 'http://127.0.0.1:9200/my_index/product/_search?pretty=1'  -d '
{
   "filter" : {
      "and" : [
         {
            "term" : {
               "color" : "blue"
            }
         },
         {
            "term" : {
               "type" : "A"
            }
         }
      ]
   },
   "facets" : {
      "color" : {
         "terms" : {
            "field" : "color"
         },
         "facet_filter" : {
            "term" : {
               "type" : "A"
            }
         }
      },
      "type" : {
         "terms" : {
            "field" : "type"
         },
         "facet_filter" : {
            "term" : {
               "color" : "blue"
            }
         }
      }
   }
}
'

# [Wed Jan 18 19:58:25 2012] Response:
# {
#    "hits" : {
#       "hits" : [],
#       "max_score" : null,
#       "total" : 0
#    },
#    "timed_out" : false,
#    "_shards" : {
#       "failed" : 0,
#       "successful" : 5,
#       "total" : 5
#    },
#    "facets" : {
#       "color" : {
#          "other" : 0,
#          "terms" : [
#             {
#                "count" : 1,
#                "term" : "red"
#             }
#          ],
#          "missing" : 0,
#          "_type" : "terms",
#          "total" : 1
#       },
#       "type" : {
#          "other" : 0,
#          "terms" : [
#             {
#                "count" : 1,
#                "term" : "C"
#             },
#             {
#                "count" : 1,
#                "term" : "B"
#             }
#          ],
#          "missing" : 0,
#          "_type" : "terms",
#          "total" : 2
#       }
#    },
#    "took" : 3
# }

Yes you can.

While you can use filters within the query DSL, the search API also accepts a top-level filter parameter, which is used for filtering the search results AFTER the facets have been calculated.

For example:

1) First, create your index, and because you want product_type to be treated as an enum, set it to be not_analyzed:

curl -XPUT 'http://127.0.0.1:9200/my_index/?pretty=1'  -d '
{
   "mappings" : {
      "product" : {
         "properties" : {
            "product_type" : {
               "index" : "not_analyzed",
               "type" : "string"
            },
            "product_name" : {
               "type" : "string"
            }
         }
      }
   }
}
'

2) Index some docs (note, doc 3 has a different product_name):

curl -XPUT 'http://127.0.0.1:9200/my_index/product/1?pretty=1'  -d '
{
   "product_type" : "A",
   "product_name" : "foo bar"
}
'
curl -XPUT 'http://127.0.0.1:9200/my_index/product/2?pretty=1'  -d '
{
   "product_type" : "B",
   "product_name" : "foo bar"
}
'
curl -XPUT 'http://127.0.0.1:9200/my_index/product/3?pretty=1'  -d '
{
   "product_type" : "C",
   "product_name" : "bar"
}
'

3) Perform a search for products whose name contains foo (which excludes doc 3 and thus product_type C), calculate facets for product_type for all docs which have foo in the product_name, then filter the search results by product_type == A:

curl -XGET 'http://127.0.0.1:9200/my_index/product/_search?pretty=1'  -d '
{
   "query" : {
      "text" : {
         "product_name" : "foo"
      }
   },
   "filter" : {
      "term" : {
         "product_type" : "A"
      }
   },
   "facets" : {
      "product_type" : {
         "terms" : {
            "field" : "product_type"
         }
      }
   }
}
'

# {
#    "hits" : {
#       "hits" : [
#          {
#             "_source" : {
#                "product_type" : "A",
#                "product_name" : "foo bar"
#             },
#             "_score" : 0.19178301,
#             "_index" : "my_index",
#             "_id" : "1",
#             "_type" : "product"
#          }
#       ],
#       "max_score" : 0.19178301,
#       "total" : 1
#    },
#    "timed_out" : false,
#    "_shards" : {
#       "failed" : 0,
#       "successful" : 5,
#       "total" : 5
#    },
#    "facets" : {
#       "product_type" : {
#          "other" : 0,
#          "terms" : [
#             {
#                "count" : 1,
#                "term" : "B"
#             },
#             {
#                "count" : 1,
#                "term" : "A"
#             }
#          ],
#          "missing" : 0,
#          "_type" : "terms",
#          "total" : 2
#       }
#    },
#    "took" : 3
# }

4) Perform a search for foo in the product_name, but calculate facets for all products in the index, by specifying the global parameter:

# [Wed Jan 18 17:15:09 2012] Protocol: http, Server: 192.168.5.10:9200
curl -XGET 'http://127.0.0.1:9200/my_index/product/_search?pretty=1'  -d '
{
   "query" : {
      "text" : {
         "product_name" : "foo"
      }
   },
   "filter" : {
      "term" : {
         "product_type" : "A"
      }
   },
   "facets" : {
      "product_type" : {
         "global" : 1,
         "terms" : {
            "field" : "product_type"
         }
      }
   }
}
'

# [Wed Jan 18 17:15:09 2012] Response:
# {
#    "hits" : {
#       "hits" : [
#          {
#             "_source" : {
#                "product_type" : "A",
#                "product_name" : "foo bar"
#             },
#             "_score" : 0.19178301,
#             "_index" : "my_index",
#             "_id" : "1",
#             "_type" : "product"
#          }
#       ],
#       "max_score" : 0.19178301,
#       "total" : 1
#    },
#    "timed_out" : false,
#    "_shards" : {
#       "failed" : 0,
#       "successful" : 5,
#       "total" : 5
#    },
#    "facets" : {
#       "product_type" : {
#          "other" : 0,
#          "terms" : [
#             {
#                "count" : 1,
#                "term" : "C"
#             },
#             {
#                "count" : 1,
#                "term" : "B"
#             },
#             {
#                "count" : 1,
#                "term" : "A"
#             }
#          ],
#          "missing" : 0,
#          "_type" : "terms",
#          "total" : 3
#       }
#    },
#    "took" : 4
# }

UPDATE TO ANSWER THE EXPANDED QUESTION FROM THE OP:

You can also apply filters directly to each facet - these are called facet_filters.

Similar example to before:

1) Create the index:

curl -XPUT 'http://127.0.0.1:9200/my_index/?pretty=1'  -d '
{
   "mappings" : {
      "product" : {
         "properties" : {
            "color" : {
               "index" : "not_analyzed",
               "type" : "string"
            },
            "name" : {
               "type" : "string"
            },
            "type" : {
               "index" : "not_analyzed",
               "type" : "string"
            }
         }
      }
   }
}
'

2) Index some data:

curl -XPUT 'http://127.0.0.1:9200/my_index/product/1?pretty=1'  -d '
{
   "color" : "red",
   "name" : "foo bar",
   "type" : "A"
}
'

curl -XPUT 'http://127.0.0.1:9200/my_index/product/2?pretty=1'  -d '
{
   "color" : [
      "red",
      "blue"
   ],
   "name" : "foo bar",
   "type" : "B"
}
'

curl -XPUT 'http://127.0.0.1:9200/my_index/product/3?pretty=1'  -d '
{
   "color" : [
      "green",
      "blue"
   ],
   "name" : "bar",
   "type" : "C"
}
'

3) Search, filtering on products that have both type==Aand color == blue, then run facets on each attribute excluding, the "other" filter:

curl -XGET 'http://127.0.0.1:9200/my_index/product/_search?pretty=1'  -d '
{
   "filter" : {
      "and" : [
         {
            "term" : {
               "color" : "blue"
            }
         },
         {
            "term" : {
               "type" : "A"
            }
         }
      ]
   },
   "facets" : {
      "color" : {
         "terms" : {
            "field" : "color"
         },
         "facet_filter" : {
            "term" : {
               "type" : "A"
            }
         }
      },
      "type" : {
         "terms" : {
            "field" : "type"
         },
         "facet_filter" : {
            "term" : {
               "color" : "blue"
            }
         }
      }
   }
}
'

# [Wed Jan 18 19:58:25 2012] Response:
# {
#    "hits" : {
#       "hits" : [],
#       "max_score" : null,
#       "total" : 0
#    },
#    "timed_out" : false,
#    "_shards" : {
#       "failed" : 0,
#       "successful" : 5,
#       "total" : 5
#    },
#    "facets" : {
#       "color" : {
#          "other" : 0,
#          "terms" : [
#             {
#                "count" : 1,
#                "term" : "red"
#             }
#          ],
#          "missing" : 0,
#          "_type" : "terms",
#          "total" : 1
#       },
#       "type" : {
#          "other" : 0,
#          "terms" : [
#             {
#                "count" : 1,
#                "term" : "C"
#             },
#             {
#                "count" : 1,
#                "term" : "B"
#             }
#          ],
#          "missing" : 0,
#          "_type" : "terms",
#          "total" : 2
#       }
#    },
#    "took" : 3
# }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文