elasticsearch - elasticsearch must_not terms 子句不起作用
问题描述
看看这个弹性搜索查询:
{
"query": {
"bool": {
"must_not": {
"terms": {
"element_type": [
"TYPE1",
"TYPE2",
"TYPE3"
]
}
},
"should": [
{
"match_phrase": {
"myfield1": {
"query": "mykeyword"
}
}
},
{
"match_phrase": {
"myfield2": {
"query": "mykeyword"
}
}
}
]
}
}
}
我正在使用 6.2.4 版本的弹性搜索。
一切正常,但最近几天我在 element_type 字段中得到了 TYPE1、TYPE2、TYPE3 值的结果。
什么都没有改变...
你知道这个问题吗?
谢谢
* 编辑 *
我创建了一个演示该问题的 php 脚本。我已经在全新的弹性搜索安装上运行它:
<?php
function insert($doc_type,$nb)
{
for ($id=1;$id<=$nb;$id++)
{
$url = "http://localhost:9200/idx5/doc/".$doc_type.'-'.$id;
// echo $url."\n";
$ch = curl_init();
$query = array(
"id" => $id,
"element_type" => $doc_type,
"title" => 'test '.$doc_type.' '.$id
);
$query = json_encode($query);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json'));
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0);
$result = curl_exec($ch);
curl_close($ch);
$result = json_decode($result, true);
if ($result['_shards']['successful']!='1')
{
echo $query;
print_r($result);
return false;
}
}
}
insert('TYPE1',6);
insert('TYPE2',100);
$ch = curl_init();
$method = "GET";
$url = "127.0.0.1/idx5/_search?size=600";
$query = '{
"query": {
"bool": {
"must_not": {
"term" : { "element_type" : "TYPE1" }
},
"should": [
{
"match_phrase": {
"title": {
"query": "test"
}
}
}
]
}
}
}';
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_PORT, 9200);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($method));
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($ch, CURLOPT_POSTFIELDS, $query);
$result = curl_exec($ch);
curl_close($ch);
$result = json_decode($result, true);
foreach ($result['hits']['hits'] as $res)
{
$type = $res["_source"]["element_type"];
echo $type."\n";
if ($type=="TYPE1")
{
print_r($res);
die;
}
}
?>
这是我的脚本的输出:
Array
(
[_index] => idx5
[_type] => doc
[_id] => TYPE1-1
[_score] => 0.0023501774
[_source] => Array
(
[id] => 1
[element_type] => TYPE1
[title] => test TYPE1 1
)
)
我不应该在我的结果中得到 TYPE1 element_type ......
我没有映射。我认为映射是自动创建的。
有以下输出: curl http://localhost:9200/idx5:
{
"idx5": {
"aliases": {},
"mappings": {
"properties": {
"element_type": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"id": {
"type": "long"
},
"title": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
},
"settings": {
"index": {
"creation_date": "1585832833661",
"number_of_shards": "1",
"number_of_replicas": "1",
"uuid": "xxxxxx",
"version": {
"created": "xxxxx"
},
"provided_name": "idx5"
}
}
}
}
谢谢你的帮助
解决方案
尝试改用此查询,即使用element_type.keyword
而不是element_type
:
$query = '{
"query": {
"bool": {
"must_not": {
"term" : { "element_type.keyword" : "TYPE1" } <----- change here
},
"should": [
{
"match_phrase": {
"title": {
"query": "test"
}
}
}
]
}
}
}';
对此的解释如下:当您没有为字符串字段指定映射时,它们会使用text
类型和keyword
子字段创建。
因此,在索引字段中的值TEST1
时element_type
:
知道了这一点,您可以通过两种不同的方式制作 must_not 查询。
要么match
在字段上进行查询element_type
:
"match" : { "element_type" : "type1" }
或对子字段进行term
查询(具有精确值匹配)element-type.keyword
"term" : { "element_type.keyword" : "TYPE1" }
如果您真的想通过查询来查询该element_type
字段term
,那么您需要将您的值小写,如下所示(即您想对分析的值进行完全匹配):
"term" : { "element_type" : "type1" }
推荐阅读
- flutter - 打开键盘时如何显示完整的showModalBottomSheet
- python - for循环如何处理python中的字符串值?
- mysql - 使用 Reg ex 的 SQL GROUP BY 名称
- ios - Unix dateTime 格式未在 swift 5 中正确转换
- php - 检查参数是否等于模型中定义的常量
- c - 括号对范围块有什么影响?
- ionic-framework - 如何在点之间画线并保存为坐标数组 IONIC
- java - 如何在 Java 中对函数外的代码使用条件编译?
- react-native - 如何在 React-Native 中检查对 Touch ID、Face ID、密码和模式锁定的支持
- sql-server - 如何将 SQL 命令转换为实体框架和 Lambda 表达式