弹性在PHP中搜索多个范围

时间:2015-02-10 18:30:32

标签: elasticsearch

我一直盯着我的显示器长时间不问:如何使用弹性搜索PHP库执行多范围查询

我正在尝试根据价格标准(少于和多于)和产品数量在其类别中查询我的指数(最少2个产品,仅限2个产品等)

虽然$searchParams['body']['query']['range']['number_of_products'] = ['gte' => $products + 1]; 本身工作正常,但与

结合使用
$searchParams['body']['query']['range']['price'] = [
    'gte' => $price['min'],
    'lte' => $price['max'],
];

我很难找到一个体面的最新例子,涵盖ES v0.9之后的这个场景,这在我的v1.4.2上失败了。

2 个答案:

答案 0 :(得分:5)

你的答案是对的。另外,如果您使用bool过滤器而不是and/or/not过滤器集,性能会更好。情况并非如此,但通常都是如此。

和/或/不适用于"越级迭代器"图案。这会在第一个过滤器中找到第一个匹配的文档,然后尝试跳过"跳过"其余的过滤器迭代器直到它们都在同一个doc上对齐。这使得它对稀疏滤波器有效。

相比之下,Bool过滤器按比特组合位图(代表匹配的文档),这对于更密集的过滤器更有效。您的过滤器看起来相对密集:

  • number_of_products过滤器全部是values >= $products['min'],可能是大量匹配的文档......所有文件都在一个连续的范围内
  • price滤镜的密度取决于范围的大小,但也可能非常密集(和连续)。如果没有$ price [' max'],它也无限无限。

在实践中,bool倾向于提供比和/或/更好的性能,并且可能在此示例中,但是YMMV。 :)

$searchParams = [
    'index' => 'my_index',
    'type' => 'my_type',
    'body' => [
        'query' => [
            'filtered' => [
                'filter' => [
                    'bool' => [
                        'must' => [
                            [
                                'range' => [
                                    'number_of_products' => [
                                        'gte' => $products['min']
                                    ]
                                ]
                            ],
                            [
                                'range' => [
                                    'price' => [
                                        'gt' => $price['min'],
                                        'lt' => ($price['max'] ? : null)
                                    ]
                                ]
                            ]
                        ]
                    ]
                ]
            ]
        ]
    ]
];

答案 1 :(得分:1)

感谢这些文章:

我终于想出了一个有效的解决方案:

$searchParams['body']['query']['filtered']['filter']['and'][]['range']['number_of_products'] = ['gte' => $products['min']];
$searchParams['body']['query']['filtered']['filter']['and'][]['range']['price'] = [
            'gt' => $price['min'],
            'lt' => ($price['max'] ? : null),
        ];