过滤elasticsearch中的空数组字段

时间:2013-12-27 10:31:52

标签: elasticsearch

我的文档结构类似于:

{
    title: string,
    description: string,
    privacy_mode: string,
    hidden: boolean,
    added_by: string,
    topics: array
}

我正在尝试查询elasticsearch。但是我不想要任何带有空主题数组字段的文档。

下面是一个构建查询对象的函数:

function getQueryObject(data) {
    var orList = [{ "term": {"privacy_mode": "public", "hidden": false} }]
    if (data.user) {
        orList.push({ "term": {"added_by": data.user} });
    }

    var queryObj = {
        "fields": ["title", "topics", "added_by", "img_url", "url", "type"],
        "query": {
            "filtered" : {
                "query" : {
                    "multi_match" : {
                        "query" : data.query + '*',
                        "fields" : ["title^4", "topics", "description^3", "tags^2", "body^2", "keywords",
                                "entities", "_id"]
                    }
                },
                "filter" : {
                    "or": orList
                },
                "filter" : {
                    "limit" : {"value" : 15}
                },
                "filter": {
                   "script": {
                        "script": "doc['topics'].values.length > 0"
                   }
               }
            }
        }
    }
    return queryObj;
};

这仍然给我带有空主题数组的元素。想知道什么是错的!

感谢您的帮助

2 个答案:

答案 0 :(得分:13)

你可能想要missing-filter。您的脚本方法会将所有主题的值加载到内存中,如果您不是这样,那将非常浪费。面对他们。

此外,您的过滤器结构错误。您不能为filter重复使用值,但应使用bool - 过滤器对其进行换行。 (这就是您通常希望使用bool而不是and|or|not的原因:http://www.elasticsearch.org/blog/all-about-elasticsearch-filter-bitsets/

最后,您可能希望在搜索对象上指定size,而不是使用limit - 过滤器。

我制作了一个可以玩的可运行示例:https://www.found.no/play/gist/aa59b987269a24feb763

#!/bin/bash

export ELASTICSEARCH_ENDPOINT="http://localhost:9200"

# Index documents
curl -XPOST "$ELASTICSEARCH_ENDPOINT/_bulk?refresh=true" -d '
{"index":{"_index":"play","_type":"type"}}
{"privacy_mode":"public","topics":["foo","bar"]}
{"index":{"_index":"play","_type":"type"}}
{"privacy_mode":"private","topics":[]}
'

# Do searches

curl -XPOST "$ELASTICSEARCH_ENDPOINT/_search?pretty" -d '
{
    "query": {
        "filtered": {
            "filter": {
                "bool": {
                    "must": [
                        {
                            "term": {
                                "privacy_mode": "public"
                            }
                        }
                    ],
                    "must_not": [
                        {
                            "missing": {
                                "field": "topics"
                            }
                        }
                    ]
                }
            }
        }
    }
}
'

答案 1 :(得分:6)

关键字missing自ES5.0后删除,建议使用exists(请参阅here):

curl -XGET 'localhost:9200/_search?pretty' -H 'Content-Type: 
application/json' -d'
{
    "query": {
        "bool": {
            "must_not": {
                   "exists": {
                       "field": "topics"
                   }
            }
        }
    }
}'