elasticsearch must_not 条款条款无效
elasticsearch must_not terms clause is not working
看看这个 elasticsearch 查询:
{
"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
子字段创建。
因此,当在您的 element_type
字段中索引值 TEST1
时:
test1
将在 element_type
字段中建立索引(文本字段默认由 standard analyzer 分析)
TEST1
将在 element_type.keyword
子字段中编入索引(keyword fields 未按原样分析和编入索引)
知道了这一点,您就可以用两种不同的方式制作 must_not 查询。
在 element_type
字段上使用 match
查询:
"match" : { "element_type" : "type1" }
或在 element-type.keyword
子字段上使用 term
查询(具有精确值匹配)
"term" : { "element_type.keyword" : "TYPE1" }
如果你真的想用 term
查询来查询 element_type
字段,那么你需要将你的值小写,就像这样(即你想对分析的值进行精确匹配):
"term" : { "element_type" : "type1" }
看看这个 elasticsearch 查询:
{
"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
子字段创建。
因此,当在您的 element_type
字段中索引值 TEST1
时:
test1
将在element_type
字段中建立索引(文本字段默认由 standard analyzer 分析)TEST1
将在element_type.keyword
子字段中编入索引(keyword fields 未按原样分析和编入索引)
知道了这一点,您就可以用两种不同的方式制作 must_not 查询。
在 element_type
字段上使用 match
查询:
"match" : { "element_type" : "type1" }
或在 element-type.keyword
子字段上使用 term
查询(具有精确值匹配)
"term" : { "element_type.keyword" : "TYPE1" }
如果你真的想用 term
查询来查询 element_type
字段,那么你需要将你的值小写,就像这样(即你想对分析的值进行精确匹配):
"term" : { "element_type" : "type1" }