有条件地将术语过滤器添加到 elasticsearch 过滤器查询

Conditionally adding term filters to elasticsearch filter query

我一直想知道如何在实际将该术语过滤器添加到过滤查询之前检查搜索参数是否不为空。从我对 elasticsearch 的有限经验来看,我似乎必须提前构建我的确切查询。

如果我使用的是 Node / Mongo,我知道我可以按照

的方式做一些事情
var searchTerms = {};
if(req.body.country){
  searchTerm['user.country'] = req.body.country;
}

if(req.body.company){
  searchTerm['user.company'] = req.body.company;
}

if(req.body.salary){
  searchTerm['user.salary'] = req.body.salary;
}

Users.find(searchTerm)
  .exec(function(err, users) {
    if(!err){
      res.send(200, users);    
    }
    else{
      res.send(200, err);
    }
 });    

并且在 angular 中,我为 elasticsearch 构建了一个查询,只要填写了所有参数,该查询就可以正常工作。我想我的问题是如何根据具有的参数有条件地和动态地构建过滤查询已由用户填写

即用户 A 填写了国家和公司,但没有填写工资。因此,工资不会作为术语过滤器包含在内。

client.search({
  index: 'firebase',
  type: 'user',
  body: {
    "query": {
       "filtered" : {
           "query" : {
               "match_all" : {}
             },
             "filter": {
                "and": [
                    {
                      "term": { "country" : searchParameters.country }
                    },
                    {
                      "term": { "company" : searchParameters.company }
                    },
                    {
                      "term": { "salary" : searchParameters.salary }
                    }
                ]
             }

       }
 }

提前谢谢大家!

您为 Node/Mongo 所做的工作就是您描述的 Elasticsearch 查询方式。

因此您的 JS 代码可能类似于:

var filters = [];
var fields = ['country', 'company', 'salary',...]; // or some kind of hash to map req fields to elasticsearch fields if appropriate
for(var k = 0; k < fields.length; k++) {
    if(req.body[fields[k]]) {
        var termq = { term : {} };
        termq.term[fields[k]] = req.body[fields[k]];
        filters.push(termq);
    }
}

var query = {
    filtered : {
        query : { match_all : {} },
        filter : filters.length ? { and : filters } : {}
    }
};

client.search({ index: ..., type: ..., body: query }, ...);