【问题标题】:Elasticsearch seach using wildcard, range and terms使用通配符、范围和术语的 Elasticsearch 搜索
【发布时间】:2021-05-22 05:01:21
【问题描述】:

我正在尝试在 Elasticsearch(7.1 版)索引上编写搜索 DSL 查询,该索引具有 product_name、exported_at 和 category_id 等字段。

从文档中我了解到,我需要使用通配符、范围来搜索日期字段和术语来过滤所需的 category_id。

示例:我需要过滤其 SQL 为的数据:

SELECT * from products table
WHERE product_name LIKE '%geography%'
AND exported_at >= '2020-01-01' AND exported_at <= '2020-12-31'
AND category_id IN [10,20,30,40]

以下更新代码:

// Creating new index
$params = [
    'index' => PS_ELASTIC_INDEX,
    'body' => [
        'mappings' => [
            'properties' => ['wc_product_name' => ["type" => "wildcard"]]
        ],
    ]
];

$response_create = $this->client->indices()->create($params);

//Storing data to the Index
//$rows contain the data fetch from the DB

foreach($rows as $row ) {
    
    $data['body'][] = [
        'id'                => $row->id,
        'wc_product_name'   => $row->product_name,
        'category_id'       => $row->category_id,
        'exported_at'       => $row->exported_at,
    ]
}

//Search the Elastic search index

$keyword  = $requestVars['product_name'];

$filters = [];

$filters[] = [
    'wildcard' => [
            'wc_product_name' => [
            'value' => '*'.$keyword.'*', 
        ],
    ]
];

$filters[] = [
    "range" => [
        "exported_on" =>  [
            "gte" => $requestVars['date_from'],
            "lte" => $requestVars['date_to'],
            "boost" => 2.0
        ]
    ],
];

if(!empty($requestVars['categories'])) {
    $filters[] = [
        "terms" => [
            "category_id" => $requestVars['categories'],
            "boost" => '1.0'
        ],
    ];
}   

$params = [
    'index' => PS_ELASTIC_INDEX,
    'body' => [
        'query' => [
            'bool' => [ 'filter' => $filters ]
        ]
    ]
];

$data = $this->client->search($params);

现在的问题是,如果使用像“地理”这样的单个词作为它工作的产品名称,搜索就可以工作,而搜索像“亚洲地理”这样的多个词将不起作用。

【问题讨论】:

    标签: php elasticsearch elasticsearch-php


    【解决方案1】:

    您缺少 bool/filter 查询以封装您的三个条件:

      'body' => [
          'query' => [
            'bool' => [
              'filter' => [
                 [
                    'wildcard' => [
                            'product_name' => [
                            'value' => "*".$keyword."*", 
                            'boost' => 1.0,
                            'rewrite' => 'constant_score'
                        ],
                    ]
                 ],
                 [
                    "range" => [
                        "exported_on" =>  [
                            "gte" => $requestVars['date_from'],
                            "lte" => $requestVars['date_to'],
                            "boost" => 2.0
                        ]
                    ],
                 ],
                 [
                    "terms" => [
                        "category_id" => [10,20,30,40],
                        "boost" => '1.0'
                    ]
                 ],
              ]
          ]
       ]
     ]
    

    【讨论】:

    • 感谢@Val,这似乎几乎可以工作,除了产品名称关键字有多个单词的情况,例如适用于地理,但是如果我搜索“亚洲地理”,它不会显示任何结果。
    • 是的,为此您需要使用wildcard field 类型而不是关键字
    • 我已经更新了上面的帖子,请您检查并建议我可能做错了什么?
    • 有什么问题?有什么错误可以分享吗?
    • 不,没有这样的错误。如果我在产品名称搜索中使用两个词,则返回的数据为空。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-24
    • 2020-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多