对于弹性搜索索引,如何获取数组字段长度大于0的文档?

问题描述

在弹性搜索索引中,如何获取数组字段长度大于0的文档?

我尝试使用多种语法,但没有任何突破。我在所有语法中都遇到了相同的错误

获取http:// {{host}}:{{elasticSearchPort}} / student_details / _search

语法1:

{
  "query": {
    "bool": {
      "filter": {
        "script": {
          "script": {
            "source": "doc['enrolledCourses'].values.length > 0","lang": "painless"
          }
        }
      }
    }
  }
}

错误

"caused_by": {
  "type": "illegal_argument_exception","reason": "No field found for [enrolledCourses] in mapping with types []"
}

语法2:

{
  "query": {
    "bool": {
      "filter": {
        "script": {
          "script": {
            "source": "doc['enrolledCourses'].values.size() > 0","reason": "No field found for [enrolledCourses] in mapping with types []"
}

语法3:

{
  "query": {
    "bool": {
      "filter" : {
        "script" : {
          "script" : "doc['enrolledCourses'].values.size() > 0"
         }
      }
    }
  }
}

错误

"caused_by": {
  "type": "illegal_argument_exception","reason": "No field found for [enrolledCourses] in mapping with types []"
}

语法4:

{
  "query": {
    "bool": {
      "filter" : {
        "script" : {
          "script" : "doc['enrolledCourses'].values.length > 0"
         }
      }
    }
  }
}

错误

"caused_by": {
  "type": "illegal_argument_exception","reason": "No field found for [enrolledCourses] in mapping with types []"
}   

请帮助我解决这个问题。

解决方法

我不知道您运行的是哪个版本的Elastic,然后我的所有测试都将在最新的7.9.0版本的Elasticsearch上运行。

我将使用轻松的脚本编写脚本。

我对文档进行了索引测试:

PUT test/_doc/1
{
   "name": "Vasia","enrolledCourses" : ["test1","test2"]
}

PUT test/_doc/2
{
   "name": "Petya"
}

如何查看一个文档包含enrolledCourses字段,而第二个文档不包含。

在轻松的情况下,您不需要使用值字段,而可以直接获取长度,这是根据painless documentation得出的。然后,我在脚本中跳过使用values运算符:

GET test/_search
{
   "query": {
      "bool": {
        "filter": [
          {
            "script": {
              "script": {
                "source": "doc['enrolledCourses'].length > 0","lang": "painless"
              }
            }
          }
        ]
      }
   }
}

运行后,我收到两个不同的错误:

{
          "type" : "script_exception","reason" : "runtime error","script_stack" : [
            "org.elasticsearch.index.mapper.TextFieldMapper$TextFieldType.fielddataBuilder(TextFieldMapper.java:757)","org.elasticsearch.index.fielddata.IndexFieldDataService.getForField(IndexFieldDataService.java:116)","org.elasticsearch.index.query.QueryShardContext.lambda$lookup$0(QueryShardContext.java:331)","org.elasticsearch.search.lookup.LeafDocLookup$1.run(LeafDocLookup.java:97)","org.elasticsearch.search.lookup.LeafDocLookup$1.run(LeafDocLookup.java:94)","java.base/java.security.AccessController.doPrivileged(AccessController.java:312)","org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:94)","org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:41)","doc['enrolledCourses'].length > 0","    ^---- HERE"
          ]
}

and
{
            "type" : "illegal_argument_exception","reason" : "Text fields are not optimised for operations that require per-document field data like aggregations and sorting,so these operations are disabled by default. Please use a keyword field instead. Alternatively,set fielddata=true on [enrolledCourses] in order to load field data by uninverting the inverted index. Note that this can use significant memory."
}

两个错误都很明显。首先是不存在该字段的文档,其次是因为Elasticsearch将字符串数组字段索引为默认映射类型text

通过将enrolledCourses字段映射为keyword,很容易解决这两种情况。 在第一种情况下,映射将始终提供空白字段,而在第二种关键字中,则允许运行fielddata属性。

PUT test 
{
   "settings": {
     "number_of_replicas": 0
   },"mappings": {
      "properties": {
         "name": {
           "type": "keyword"
         },"enrolledCourses": {
            "type": "keyword"
         }
      }
   }
}

现在,我将收到查询的正确答案:

{
  "took" : 0,"timed_out" : false,"_shards" : {
    "total" : 1,"successful" : 1,"skipped" : 0,"failed" : 0
  },"hits" : {
    "total" : {
      "value" : 1,"relation" : "eq"
    },"max_score" : 0.0,"hits" : [
      {
        "_index" : "test","_type" : "_doc","_id" : "1","_score" : 0.0,"_source" : {
          "name" : "Vasia","enrolledCourses" : [
            "test1","test2"
          ]
        }
      }
    ]
  }
}