elasticsearch nested嵌套对象全文检索和排序

 

什么是 ES Nested 嵌套类型? Elasticsearch 有很多数据类型,大致如下:

  • 基本数据类型: string 类型。ES 7.x 中,string 类型会升级为:text 和 keyword。keyword 可以排序;text 默认分词,不可以排序。
  • 数据类型:integer、long 等 
  • 时间类型、布尔类型、二进制类型、区间类型等 
  • 复杂数据类型: 
  • 数组类型:Array 
  • 对象类型:Object Nested 类型 
  • 特定数据类型:地理位置、IP 等 注意:tring/nested/array 类型字段不能用作排序字段。因此 string 类型会升级为:text 和 keyword。keyword 可以排序,text 默认分词,不可以排序。

nested 类型是一种特殊的 [object,object] 类型. 这种类型允许对 object 数组内的元素进行单独查询,区别是:

  • object: Lucene 没有内部 object 的概念, 所以 Elasticsearch 内部会把 object 解析成简单的字段名与值的信息,就是所有字段平铺。 
  • nested: Elasticsearch 内部会把数组中的每个元素当成一个隐藏文档, 所以可以用 [query-dsl-nested-query,nested query] 

嵌套模型的优缺点如下:

  • 文档存储在一起,因此读取性能高
  • 如果新增丶修改或删除一个嵌套文档,则必须重新索引整个文档。因此越多嵌套文档造成越多的成本。

动态映射 字段数据类型不需要事先定义,ES内部自动映射默认字段类型。如果是object类型,数据同步时会把内部的text映射成text,还会带上keyowd的子类型。参考

嵌套类型搜索

object类型的filed会把text类型字段没有加上keyword,就是不分词。所以我们改成neatest类型。 因嵌套对象(nested objects)会被索引为分离的隐藏文档,我们不能直接查询它们。而是使用 nested查询或 nested 过滤器来存取它们:

GET /my_index/blogpost/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "title": "eggs" }}, <1>
        {
          "nested": {
            "path": "comments", <2>
            "query": {
              "bool": {
                "must": [ <3>
                  { "match": { "comments.name": "john" }},
                  { "match": { "comments.age":  28     }}
                ]
        }}}}
      ]
}}}

嵌套字段排序问题


PUT /my_index/blogpost/2
{
  "title": "Investment secrets",
  "body":  "What they don't tell you ...",
  "tags":  [ "shares", "equities" ],
  "comments": [
    {
      "name":    "Mary Brown",
      "comment": "Lies, lies, lies",
      "age":     42,
      "stars":   1,
      "date":    "2014-10-18"
    },
    {
      "name":    "John Smith",
      "comment": "You're making it up!",
      "age":     28,
      "stars":   2,
      "date":    "2014-10-16"
    }
  ]
}

嵌套查询

GET /_search
{
  "query": {
    "nested": { 
      "path": "comments",
      "filter": {
        "range": {
          "comments.date": {
            "gte": "2014-10-01",
            "lt":  "2014-11-01"
          }
        }
      }
    }
  },
  "sort": {
    "comments.stars": { 
      "order": "asc",   
      "mode":  "min",   
      "nested_filter": { 
        "range": {
          "comments.date": {
            "gte": "2014-10-01",
            "lt":  "2014-11-01"
          }
        }
      }
    }
  }
}

上面的方案在ES6.1之后是不行的,因为嵌套类型的排序有特殊的排序nested sort选项,开启的方式和netsed查询很像。所以我们升级了一下

POST /_search
{
   "query" : {
      "term" : { "product" : "chocolate" }
   },
   "sort" : [
       {
          "offer.price" : {
             "mode" :  "avg",
             "order" : "asc",
             "nested": {
                "path": "offer",
                "filter": {
                   "term" : { "offer.color" : "blue" }
                }
             }
          }
       }
    ]
}

java代码的写法

  BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
            RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("custom_info.deptUpdateTime");
            rangeQueryBuilder.gte(condition.getDeptUpdateTime().getStartTime() + "T00:00:00");
            rangeQueryBuilder.lte(condition.getDeptUpdateTime().getEndTime() + "T23:59:59");
            boolBuilder.must(rangeQueryBuilder);
            QueryBuilder nestedQueryBuilder = new NestedQueryBuilder(
                "custom_info",
                boolBuilder,
                ScoreMode.None
            );
            

参考文档

netst——path

ElasticSearch的Nested(嵌套)数据类型

你可能感兴趣的:(搜索引擎)