使用用例更容易说明我的问题所以让我们从弹性搜索指南中获取example。
这列出了一个产品。每个产品都有一个嵌套数组,其中包含销售该产品的经销商:
{
...
"product" : {
"properties" : {
"resellers" : {
"type" : "nested",
"properties" : {
"name" : { "type" : "text" },
"price" : { "type" : "double" }
}
}
}
}
}
如果可能的话,我该如何做?
product.resellers[name=storeA].price < product.resellers[name=storeB].price
这可能需要分别使用脚本过滤器和订单过滤器,但不确定如何进行此操作。此外,经常使用这些类型的查询,因此性能很重要。因此,我可能需要坚持使用docValues而不是诉诸_source
。这可能吗?
答案 0 :(得分:1)
是的,这绝对是可能的,你可以这样做:
{
"sort": {
"_script": {
"type": "number",
"script": {
"inline": "def store1 = _source.resellers.find{it.name == store1}; def store2 = _source.resellers.find{it.name == store2}; (store1 != null && store2 != null) ? store1.price - store2.price : 0",
"lang": "groovy",
"params": {
"store1": "storeA",
"store2": "storeB"
}
},
"order": "asc"
}
},
"query": {
"bool": {
"filter": [
{
"script": {
"script": {
"inline": "def store1 = _source.resellers.find{it.name == store1}; def store2 = _source.resellers.find{it.name == store2}; (store1 != null && store2 != null) ? store1.price < store2.price : false",
"lang": "groovy",
"params": {
"store1": "storeA",
"store2": "storeB"
}
}
}
}
]
}
}
}
排序脚本如下所示:
def store1 = _source.resellers.find{it.name == store1};
def store2 = _source.resellers.find{it.name == store2};
(store1 != null && store2 != null) ? store1.price - store2.price : 0
过滤器脚本有点类似,如下所示:
def store1 = _source.resellers.find{it.name == store1};
def store2 = _source.resellers.find{it.name == store2};
(store1 != null && store2 != null) ? store1.price < store2.price : false
两个脚本都在输入中使用两个参数,即您要比较的经销商商店的名称。
<强>更新强>
不知何故,我忘了解释为什么不能用doc值来做这件事。 Doc值实际上是倒排索引的倒数,即向每个文档映射存在于该文档内的令牌。这与嵌套文档作为独立(但隐藏)文档存储在索引中的事实相结合,文档的doc值如下所示
{
"id": 1,
"product": "Water",
"resellers": [
{
"name": "storeA",
"price": 20
},
{
"name": "storeB",
"price": 30
}
]
}
看起来像这样:
Document | Values
----------------+---------------------------
1 (top-level) | water
1a (1st nested} | storea, 20
1b (2nd nested} | storeb, 30
查看上表,并且由于脚本是在每个文档的上下文中执行的(无论是顶层还是嵌套),因此当访问脚本中的doc值时,只会产生该文档的值,因此无法将它们与另一个文档中的值进行比较。
访问源代码时,我们会有效地迭代resellers
数组,因此可以比较它们之间的值,并产生在您的上下文中有用的内容。
答案 1 :(得分:0)
这看起来像是一个市场问题。所以我会根据他们的主产品ID分离产品 - 所以产品可以有不同的描述,属性等 - 并添加优先级进行排序和过滤。
{
...
"product" : {
"properties" : {
"masterProduct" : "int",
"priority" : "int",
"resellers" : {
"type" : "nested",
"properties" : {
"name" : { "type" : "text" },
"price" : { "type" : "double" }
}
}
}
}
}
让我解释一下; 首先,
product.resellers [name = storeA] .price&lt; roduct.resellers [名称= storeB]。价格
我想这个问题引发了,因为你想在搜索结果中显示最便宜的产品。因此,我认为在索引产品时,您应该拥有所有经销商的价格。
如果你知道最便宜的索引,那么它的优先级就像1那样的正数。并且将其他产品乘以-1,这样你就可以在产品细节中对它们进行分类,价格昂贵。 这解决了第二个问题(按商店A和商店B的价格之间的差异订购产品)。
毕竟你的指数中有正面优先级和负面优先级。所有你可以优先制作过滤器&gt; 0为您提供最便宜的产品。因此,如果任何经销商希望成为搜索结果的顶端或者宣传自己,那么优先级可以通过增加优先级来实现。