[英]How to do multi sort in Elastic Search
I need to divide my search result into two parts.我需要将我的搜索结果分成两部分。 1 with those goods in which the number> 0 sort them by price and withdraw first. 1 对数量>0 的商品按价格排序,先提货。 2 products whose quantity = 0 sort by price and display at the end, after those products that are in stock. 2个数量=0的产品按价格排序,最后显示在有库存的产品之后。 The main thing is that in the first group of goods (whose quantity> 0) there were no goods from the second group (whose quantity = 0) What unfortunately happens when I sort by two conditions主要是在第一组货物(数量> 0)中没有第二组货物(数量= 0)当我按两个条件排序时不幸发生了什么
Use PHP 7.1 and Elastic Search 6.6.0使用 PHP 7.1 和 Elastic Search 6.6.0
Small example, there is a table of goods小例子,有一张商品表
id | site_price | count
1 | 10 | 0
2 | 5 | 5
3 | 15 | 2
4 | 20 | 10
5 | 15 | 0
I need to sort first by quantity, and then by price (without losing the first sorting).我需要先按数量排序,然后按价格排序(不丢失第一个排序)。 First sort: ('count'=>'desc')
.第一种: ('count'=>'desc')
。 Second sort: ('site_price'=>'asc')
.第二类: ('site_price'=>'asc')
。 Should get this result:应该得到这个结果:
id | site_price | count
2 | 5 | 10
3 | 15 | 5
4 | 20 | 2
1 | 10 | 0
5 | 15 | 0
$this->params['body'] = array(
'from' => ($filters['page'] - 1) * 15,
'size' => 15,
'query' => array(
'bool' => array(
'must' => array(
"query_string" => array(
'query' => "*" . $filters['text'] . "*",
)
),
)
),
'sort' => array(
array("shops_count" => "desc"),
array("site_price" => "asc")
)
);
$result = $this->client->search($this->params);
@Nikolay, thanks for the help. @Nikolay,感谢您的帮助。 Unfortunately, this did not help.不幸的是,这没有帮助。 I tried rewrote the query - but the result is the same.我尝试重写查询 - 但结果是一样的。 Here is an example: removed too much left only search and sorting这是一个例子:删除了太多只剩下搜索和排序
enter code here
$this->params['body'] = array(
'from' => ($filters['page'] - 1) * 15,
'size' => 15,
'query' => array(
'bool' => array(
'must' => array(
"query_string" => array(
'query' => "*" . $filters['text'] . "*",
)
),
)
),
'sort' => array(
array("shops_count" => "desc"),
array("site_price" => "asc")
)
);
$result = $this->client->search($this->params);
It looks like that you want to achieve behavior similar to UNION in SQL, since you first want to split the result set into 2 groups, sort each group and then attach one group after another.看起来你想在 SQL 中实现类似于UNION 的行为,因为你首先想将结果集分成 2 组,对每组进行排序,然后一个接一组地附加。
There are a few ways to do it.有几种方法可以做到。
Like in this answer , it is suggested to do 2 queries:就像在这个答案中一样,建议做 2 个查询:
POST /orders/_search
{
"query": {
"range": {
"count": {
"gt": 0
}
}
},
"sort" : [
{"site_price": "asc"},
]
}
POST /orders/_search
{
"query": {
"range": {
"count": {
"gte": 0,
"lte": 0
}
}
},
"sort" : [
{"site_price": "asc"},
]
}
And then joining them on the client side.然后在客户端加入他们。 There is also a way to do it completely on the Elasticsearch side.还有一种方法可以在 Elasticsearch 端完全做到这一点。
We can use script based sorting and sort first on the availability ( count > 0
), then by price:我们可以使用基于脚本的排序,首先根据可用性( count > 0
)排序,然后按价格排序:
POST /orders/_search
{
"sort" : [
{
"_script" : {
"type" : "number",
"script" : {
"lang": "painless",
"source": "if (doc['count'].value > 0) { 1 } else { 0 } "
},
"order" : "desc"
}
},
{"site_price": "asc"}
]
}
However, scripting always has performance overhead.然而,脚本总是有性能开销。 Solution #1 is more robust, although it performs 2 queries.解决方案#1 更健壮,尽管它执行了 2 个查询。
Here is another solution that uses single query and does not use expensive scripting.这是另一种使用单一查询且不使用昂贵脚本的解决方案。
If we add a special field, "available"
, we will not need to use script sorting.如果我们添加一个特殊字段"available"
,我们将不需要使用脚本排序。
The documents might look like this:文档可能如下所示:
doc1 = {
"id": 1,
"site_price": 10,
"count": 0,
"available": 0
}
doc2 = {
"id": 2,
"site_price": 5,
"count": 5,
"available": 1
}
Then the sorting will look like this:然后排序将如下所示:
POST /orders/_search
{
"sort" : [
{"available": "desc"},
{"site_price": "asc"}
]
}
This is a common pattern called denormalization which proves useful when tuning for best performance.这是一种称为非规范化的常见模式,在调整以获得最佳性能时证明是有用的。
Hope that helps!希望有帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.