2017-03-15 48 views
0

更容易用一个用例来说明我的问题,所以让我们从elasticsearch指南中获得example对嵌套数组中包含的两个值之间的差异进行过滤/排序(仅使用脚本过滤器和doc值)

这列出了一个产品。每个产品都有含经销商嵌套数组,出售产品说:

{ 
     ... 

     "product" : { 
      "properties" : { 
       "resellers" : { 
        "type" : "nested", 
        "properties" : { 
         "name" : { "type" : "text" }, 
         "price" : { "type" : "double" } 
        } 
       } 
      } 
     } 
    } 

我会怎么做,如果在所有可能的下?

  • 过滤所有storeA比storeB便宜的产品。例如为:product.resellers[name=storeA].price < product.resellers[name=storeB].price
  • 订购产品通过storeA的价格和商店B

这可能分别需要一个脚本过滤和阶滤波器,但不知道我怎么会去这之间的差异。而且,这些类型的查询经常使用,因此性能很重要。因此,我可能需要坚持docValues而不是诉诸于_source。这可能吗?

回答

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 

这两个脚本在输入中都带有两个参数,即经销商的名称将您w蚂蚁来比较。

UPDATE

不知怎的,我忘了解释为什么它不可能与DOC值做到这一点。 Doc值实际上是倒排索引的倒数,即每个文档都被映射为该文档内存在的令牌。这再加上嵌套的文件保存为独立的(但隐藏)在索引文件的事实,像下面

{ 
    "id": 1, 
    "product": "Water", 
    "resellers": [ 
    { 
     "name": "storeA", 
     "price": 20 
    }, 
    { 
     "name": "storeB", 
     "price": 30 
    } 
    ] 
} 

的一个文档的DOC值应该是这样的:

Document  | Values 
----------------+--------------------------- 
1 (top-level) | water 
1a (1st nested} | storea, 20 
1b (2nd nested} | storeb, 30 

查看上面的表格,并且由于脚本是在每个文档的上下文中执行的(无论是顶层还是嵌套),显而易见的是,当访问脚本中的doc值时只会生成该文档的值,因此它无法将它们与另一个文档中的值进行比较。

访问源代码时,我们有效地遍历了resellers数组,因此可以比较它们之间的值并生成在您的上下文中很有用的东西。

+0

在此操作。同意这将工作,但根据原始问题,我正在寻找一种涉及doc值的解决方案,而不是使用'_source',因为使用'_source'需要(相当于)全表扫描,这对于我的目的来说太慢。如果这是不可能的,那么我会很好地解释为什么不这样做。谢谢 –

+1

你是对的,我忘记了包括为什么不能用doc值来做到这一点。 – Val

0

这看起来像一个市场问题。所以我会根据产品的主产品编号分开产品 - 因此产品可以有不同的描述,产品等等,并将它们添加到排序和过滤的优先级。

{ 
     ... 

     "product" : { 
      "properties" : { 
       "masterProduct" : "int", 
       "priority" : "int", 
       "resellers" : { 

        "type" : "nested", 
        "properties" : { 
         "name" : { "type" : "text" }, 
         "price" : { "type" : "double" } 
        } 
       } 
      } 
     } 
    } 

让我来解释一下, 首先,

product.resellers [名称= storeA]。价格< roduct.resellers [名称= storeB]。价格

我猜的,因为你提的这个问题要显示在最便宜的产品搜索结果。所以我认为在索引产品时,您应该拥有所有经销商的价格。

如果您知道索引编制时最便宜的优先级,那么它的优先级为1,并将其他产品与-1相乘,以便您可以将产品详细信息以低成本进行分类。 这解决了第二个问题(以storeA的价格和商店B之间的差异来订购产品)。

毕竟你在索引中获得了积极的优先级和负面的优先级。所有你可以按优先顺序制作过滤器> 0返回最便宜的产品。因此,如果任何经销商希望成为搜索结果的顶部或者宣传自己,则优先考虑优先选择

+0

这不是一个“市场”问题。我需要将任意商店与其他商店进行比较来填充统计信息显示板。但是,如果它是,你的将是一个相当优雅的解决方案。 –

相关问题