如何使用查询来区分字段是否不存在,或者它是否存在,但它的值是空数组?

ntjbwcob  于 2021-06-14  发布在  ElasticSearch
关注(0)|答案(1)|浏览(372)

我想要实现的是:
如果字段不存在,则应返回此文档。
如果字段存在但其值为空数组,则不应返回此文档。
似乎我不能使用exists查询,因为它不能区分这两种情况。
我应该用下面这样的东西吗?

GET /_search
{
  "query": {
    "bool": {
      "must_not": {
        "exists": {
          "field": "weekly_hours.monday_hours"
        }
      },
      "filter": {
        "script": {
          "script": {
            "source": "doc['weekly_hours.monday_hours'].size != 0",
            "lang": "painless"
          }
        }
      }
    }
  }
}

这样,上述两种情况都会出现 truemust_not 节,然后在 filter 第二种情况将被过滤掉,因为它的大小是0。
对吗?
有没有更简单的方法?
提前谢谢!
更新:
我试过上面提到的剧本。我想这个主意行得通不过是个例外 Fielddata is not supported on field [weekly_hours.monday_hours] of type [date_range] 发生,如下所示。

{
    "took": 12,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 4,
        "failed": 1,
        "failures": [
            {
                "shard": 3,
                "index": "items",
                "node": "jRtjvF1mTzG_jPTqkDo2uA",
                "reason": {
                    "type": "script_exception",
                    "reason": "runtime error",
                    "script_stack": [
                        "org.elasticsearch.index.mapper.MappedFieldType.fielddataBuilder(MappedFieldType.java:103)",
                        "org.elasticsearch.index.fielddata.IndexFieldDataService.getForField(IndexFieldDataService.java:111)",
                        "org.elasticsearch.search.lookup.LeafDocLookup$1.run(LeafDocLookup.java:87)",
                        "org.elasticsearch.search.lookup.LeafDocLookup$1.run(LeafDocLookup.java:84)",
                        "java.security.AccessController.doPrivileged(Native Method)",
                        "org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:84)",
                        "doc['weekly_hours.monday_hours'].size() != 0",
                        "    ^---- HERE"
                    ],
                    "script": "doc['weekly_hours.monday_hours'].size() != 0",
                    "lang": "painless",
                    "caused_by": {
                        "type": "illegal_argument_exception",
                        "reason": "Fielddata is not supported on field [weekly_hours.monday_hours] of type [date_range]"
                    }
                }
            }
        ]
    },
    "hits": {
        "total": 0,
        "max_score": null,
        "hits": []
    }
}

这个 monday_hours 字段的类型为 date_range . 这是不是意味着我根本不能在这个领域使用脚本?如果是这样的话,如何达到我在问题开头描述的效果?这里真的需要帮助。。。

uurv41yg

uurv41yg1#

做一个 must_notweekly_hours.monday_hours 技术上会过滤掉所有丢失的文件 doc['weekly_hours.monday_hours'].size() != 0 不会有任何进一步的影响。我说了 technically 因为es对所有缺失值的处理方式不同——我将在下面详细说明。
更糟的是 date_range 当前字段(>=7.9)不支持 null_value 参数,这在其他字段类型中已经是可能的,并且在这样的情况下使人的生活更轻松。
我测试了一些空白区域的变体:

1.
{
  "weekly_hours":{

  }
}

2.
{
  "weekly_hours":{
    "monday_hours":{

    }
  }
}

3.
{
 "weekly_hours":{
    "monday_hours":{
      "gte":null,
      "lte":null
    }
  }
}

最后是一个有效的

{
  "weekly_hours":{
    "monday_hours":{
      "gte":"2015-10-31 12:00:00",
      "lte":"2015-11-01"
    }
  }
}

现在,我希望下面的查询只返回 4. 但事实并非如此,我认为提交一份缺陷报告是值得的:

{
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "weekly_hours.monday_hours"
          }
        },
        {
          "range": {
            "weekly_hours.monday_hours": {
              "gte": "1970-01-01",
              "lte": "2999-12-31"
            }
          }
        },
        {
          "query_string": {
            "query": "_exists_:weekly_hours AND _exists_:weekly_hours.monday_hours AND weekly_hours.monday_hours:[1970-01-01 TO 2999-12-31] AND NOT weekly_hours.monday_hours:[null TO null]"
          }
        }
      ]
    }
  }
}

最后一句话:使用起来不是更简单吗 integer_ranges 而不是 date_ranges 一周中的某一天?现在,考虑到所有这些范围都属于同一个字段类型系列,我现在就放弃它们,并遵循这个整洁的开放时间方法。

相关问题