我一直在尝试使用elasticsearch过滤那些在其正文中包含空字符串的文档。到目前为止,我没有运气。
在继续之前,我应该提一下,我已经尝试过围绕Interwebz和StackOverflow的很多“解决方案。”
因此,下面是我正在尝试运行的查询,后跟其对应项:
{
"query": {
"filtered":{
"filter": {
"bool": {
"must_not": [
{
"missing":{
"field":"_textContent"
}
}
]
}
}
}
}
}
我也尝试了以下内容:
{
"query": {
"filtered":{
"filter": {
"bool": {
"must_not": [
{
"missing":{
"field":"_textContent",
"existence":true,
"null_value":true
}
}
]
}
}
}
}
}
以下内容:
{
"query": {
"filtered":{
"filter": {
"missing": {"field": "_textContent"}
}
}
}
}
以上都没有奏效。当我确定存在包含空字符串字段的记录时,我得到一个空结果集。
如果有人能给我任何帮助,我将非常感激。
谢谢!
答案 0 :(得分:19)
如果您使用的是默认分析器(standard
),则无需分析它是否为空字符串。因此,您需要逐字索引字段(未分析)。这是一个例子:
添加一个将未标记字段编入索引的映射,如果您需要索引字段的标记化副本,则可以使用Multi Field类型。
PUT http://localhost:9200/test/_mapping/demo
{
"demo": {
"properties": {
"_content": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
接下来,索引几个文档。
/POST http://localhost:9200/test/demo/1/
{
"_content": ""
}
/POST http://localhost:9200/test/demo/2
{
"_content": "some content"
}
执行搜索:
POST http://localhost:9200/test/demo/_search
{
"query": {
"filtered": {
"filter": {
"term": {
"_content": ""
}
}
}
}
}
返回带有空字符串的文档。
{
took: 2,
timed_out: false,
_shards: {
total: 5,
successful: 5,
failed: 0
},
hits: {
total: 1,
max_score: 0.30685282,
hits: [
{
_index: test,
_type: demo,
_id: 1,
_score: 0.30685282,
_source: {
_content: ""
}
}
]
}
}
答案 1 :(得分:10)
即使使用默认分析器,您也可以进行此类搜索:使用script filter,它较慢但可以处理空字符串:
curl -XPOST 'http://localhost:9200/test/demo/_search' -d '
{
"query": {
"filtered": {
"filter": {
"script": {
"script": "_source._content.length() == 0"
}
}
}
}
}'
它会将带有空字符串的文档作为_content返回,而不需要特殊的映射
正如@js_gandalf指出的那样,对于ES> 5.0,这已被弃用。相反,您应该使用:query-> bool-> filter->脚本,如https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html
答案 2 :(得分:4)
对于那些使用弹性搜索5.2或以上的人,仍然卡住了。最简单的方法是使用关键字类型正确地重新索引数据。然后所有空值搜索都有效。像这样:
"query": {
"term": {"MY_FIELD_TO_SEARCH": ""}
}
实际上,当我重新索引数据库并重新运行查询时。它工作=)
问题是我的字段是type:text而不是关键字。将索引更改为关键字并重新编制索引:
curl -X PUT https://username:password@host.io:9200/mycoolindex
curl -X PUT https://user:pass@host.io:9200/mycoolindex/_mapping/mycooltype -d '{
"properties": {
"MY_FIELD_TO_SEARCH": {
"type": "keyword"
},
}'
curl -X PUT https://username:password@host.io:9200/_reindex -d '{
"source": {
"index": "oldindex"
},
"dest": {
"index": "mycoolindex"
}
}'
我希望这可以帮助那些因为找到那些空值而陷入困境的人。
答案 3 :(得分:2)
为了在文档中找到一个字段的空字符串,它与字段的映射高度相关,换句话说,它与index
/ analyzer
设置高度相关。
如果其索引为not_analyzed
,这意味着令牌只是空字符串,您可以使用term
查询来查找它,如下所示:
{"from": 0, "size": 100, "query":{"term": {"name":""}}}
否则,如果index
设置为analyzed
并且我相信大多数分析器会将空字符串视为空值那么
你可以使用过滤器来找到空字符串。
{"filter": {"missing": {"existence": true, "field": "name", "null_value": true}}, "query": {"match_all": {}}}
这里是您可以参考的gist脚本:https://gist.github.com/hxuanji/35b982b86b3601cb5571
顺便说一下,我查看你提供的命令,看来你不想要空字符串文件。
以上所有命令只是为了找到这些,所以只需将其放入must_not
部分bool
查询即可。
我的ES是1.0.1。
对于ES 1.3.0,目前我提供的要点找不到空字符串。似乎有报道:https://github.com/elasticsearch/elasticsearch/issues/7348。让我们等一下,看看它是怎么回事。
无论如何,它还提供了另一个命令来查找
{“query”:{ “过滤”:{ “过滤器”:{ “不是”:{ “过滤器”:{ “范围”: { “名称”: { } } } } } }}
name
是用于查找空字符串的字段名称。我在ES 1.3.2上测试了它。
答案 4 :(得分:2)
我正在使用Elasticsearch 5.3,并且遇到了上述一些问题。
以下机构为我工作。
{
"query": {
"bool" : {
"must" : {
"script" : {
"script" : {
"inline": "doc['city'].empty",
"lang": "painless"
}
}
}
}
}
}
注意:您可能需要为文本字段启用 fielddata ,默认情况下会禁用它。虽然在这样做之前我会读到这个:https://www.elastic.co/guide/en/elasticsearch/reference/current/fielddata.html。
为字段启用 fielddata ,例如索引'business'上的'city',您需要输入类型名称'record':
PUT business/_mapping/record
{
"properties": {
"city": {
"type": "text",
"fielddata": true
}
}
}
答案 5 :(得分:1)
使用Lucene查询字符串语法进行
q =!(yourfield.keyword:“”)
请参见Elastic Search参考https://www.elastic.co/guide/en/elasticsearch/reference/6.5/query-dsl-query-string-query.html#query-string-syntax
答案 6 :(得分:0)
对于嵌套字段,请使用:
curl -XGET "http://localhost:9200/city/_search?pretty=true" -d '{
"query" : {
"nested" : {
"path" : "country",
"score_mode" : "avg",
"query" : {
"bool": {
"must_not": {
"exists": {
"field": "country.name"
}
}
}
}
}
}
}'
注意:路径和字段一起构成搜索。根据您的需要进行更改。
对于常规字段:
curl -XGET 'http://localhost:9200/city/_search?pretty=true' -d'{
"query": {
"bool": {
"must_not": {
"exists": {
"field": "name"
}
}
}
}
}'
答案 7 :(得分:0)
我没有设法在文本字段中搜索空字符串。但是它似乎适用于类型关键字的字段。所以我建议如下:
delete /test_idx
put test_idx
{
"mappings" : {
"testMapping": {
"properties" : {
"tag" : {"type":"text"},
"content" : {"type":"text",
"fields" : {
"x" : {"type" : "keyword"}
}
}
}
}
}
}
put /test_idx/testMapping/1
{
"tag": "null"
}
put /test_idx/testMapping/2
{
"tag": "empty",
"content": ""
}
GET /test_idx/testMapping/_search
{
"query" : {
"match" : {"content.x" : ""}}}
}
}
答案 8 :(得分:0)
您需要通过在字段名称中添加 .content 来触发关键字索引器。根据原始索引的设置方式,以下“仅适用于”我使用AWS ElasticSearch v6.x。
获取/my_idx/_search?q=my_field.content:“”
答案 9 :(得分:0)
如果您不想或无法重新编制索引,则可以使用另一种方法。 :-)
您可以使用否定运算符和通配符来匹配任何非空字符串*
GET /my_index/_search?q=!(fieldToLookFor:*)
答案 10 :(得分:0)
在这里https://github.com/elastic/elasticsearch/issues/7515找到了解决方案 它无需重新索引即可工作。
PUT t/t/1
{
"textContent": ""
}
PUT t/t/2
{
"textContent": "foo"
}
GET t/t/_search
{
"query": {
"bool": {
"must": [
{
"exists": {
"field": "textContent"
}
}
],
"must_not": [
{
"wildcard": {
"textContent": "*"
}
}
]
}
}
}
答案 11 :(得分:0)
我正在尝试查找空字段(在具有动态映射的索引中)并将其设置为默认值,以下内容对我有用
请注意,这是在弹性7.x版本中
POST <index_name|pattern>/_update_by_query
{
"script": {
"lang": "painless",
"source": """
if (ctx._source.<field name>== "") {
ctx._source.<field_name>= "0";
} else {
ctx.op = "noop";
}
"""
}
}
我遵循了该线程的响应之一,并在其下面提出了相同的要求
GET index_pattern*/_update_by_query
{
"script": {
"source": "ctx._source.field_name='0'",
"lang": "painless"
},
"query": {
"bool": {
"must": [
{
"exists": {
"field": "field_name"
}
}
],
"must_not": [
{
"wildcard": {
"field_name": "*"
}
}
]
}
}
}
我还试图在索引中找到没有该字段的文档,并为其添加值
该主题的回复之一帮助我在下面提出
GET index_pattern*/_update_by_query
{
"script": {
"source": "ctx._source.field_name='0'",
"lang": "painless"
},
"query": {
"bool": {
"must_not": [
{
"exists": {
"field": "field_name"
}
}
]
}
}
}
感谢为此线程做出贡献的每一个人,我能够解决我的问题