Elasticsearch-对象及Nest对象

目录

ES中处理关联关系

案例1:博客和其作者关系

包含对象数组的文档 

Nested Data Type

 嵌套查询 

嵌套对象的聚合查询


ES中处理关联关系

  • 关系型数据库,一般会考虑Normalize数据,在ES中,往往考虑Denormalize数据

    • Denormalize的好处是:读的速度快/无需表连接/无需行锁

  • ES并不擅长处理关联关系,我们一般采用以下四种方法处理关联

    • 对象类型

    • 嵌套对象

    • 父子关联关系

    • 应用端关联

案例1:博客和其作者关系

  • 对象类型
    • 在每一博客的文档中都保留作者的信息

    • 如果作者信息发生变化,需要修改相关的博客文档

 #设置mapping
PUT /blog
{
  "mappings": {
    "properties": {
      "content": {
        "type": "text"
      },
      "time": {
        "type": "date"
      },
      "user": {
        "properties": {
          "city": {
            "type": "text"
          },
          "userid": {
            "type": "long"
          },
          "username": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

 #插入blog数据
PUT blog/_doc/1
{
  "content":"I like Elasticsearch",
  "time":"2019-01-01T00:00:00",
  "user":{
    "userid":1,
    "username":"Jack",
    "city":"Shanghai"
  }
}

 #文章中包含elasticsearch 作者是jack的文章
POST /blog/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {
          "content": "Elasticsearch"
        }},
        {"match": {
          "user.username": "Jack"
        }}
      ]
    }
  }
}

包含对象数组的文档 

 #设置Mappering
PUT my_movies
{
      "mappings" : {
      "properties" : {
        "actors" : {
          "properties" : {
            "first_name" : {
              "type" : "keyword"
            },
            "last_name" : {
              "type" : "keyword"
            }
          }
        },
        "title" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
}

 #插入数据
POST my_movies/_doc/1
{
  "title":"Speed",
  "actors":[
    {
      "first_name":"Keanu",
      "last_name":"Reeves"
    },

    {
      "first_name":"Dennis",
      "last_name":"Hopper"
    }

  ]
}

为什么会搜到不需要的结果???

  • 存储时,内部对象并没有考虑在内,JSON格式被处理成扁平式键值对的结构

    • actors.first_name作为一个数组

    • actors.last_name作为一个数组

  • 当多个字段进行查询时,导致了意外的搜索结果

  • 可以用Nested Data Type解决这个问题

Nested Data Type

  • Nested数据类型: 允许对象数组中的对象被独立索引

  • 使用nested和properties关键字,将所有actors索引到多个分隔的文档

  • 在内部,Nested文档会被保存在两个Luene文档中,在查询时做Join处理

#添加mappering
PUT my_movies
{
  "mappings": {
    "properties": {
      "actors": {
        "type": "nested",
        "properties": {
          "first_name": {
            "type": "keyword"
          },
          "last_name": {
            "type": "keyword"
          }
        }
      },
      "title": {
        "type": "text"
      }
    }
  }
}

#添加数据
POST my_movies/_doc/1
{
  "title":"Speed",
  "actors":[
    {
      "first_name":"Keanu",
      "last_name":"Reeves"
    },

    {
      "first_name":"Dennis",
      "last_name":"Hopper"
    }

  ]
}

#Nest查询
POST /my_movies/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "nested":{
            "path": "actors",
            "query": {
               "bool": {
                  "must": [
                    {"match": {"actors.first_name": "Keanu"}},{"match": {"actors.last_name": "Hopper"}}
                  ]
                }
              }
          }
        }
      ]
    }
  }

 嵌套查询 

  • 在内部,Nested文档被保存在两个Lucene文档中,会在查询时做Join处理

嵌套对象的聚合查询

  •  按照first_name进行分组

#按照之前的方法发现不起作用
POST my_movies/_search
{
  "size": 0,
  "aggs": {
    "actor_name": {
      "terms": {
        "field": "actors.first_name"
      }
    }
  }
}

  • 解决办法:对于嵌套对象进行聚合分析的时候,我们需要指定聚合的字段为nested 嵌套对象,并且指定路径 将我们的聚合分析,写到nested内的子聚合分析.可以看到我们的子聚合是进行聚合分析的,主聚合没有进行聚合分析工作

 POST my_movies/_search
{
  "size": 0,
  "aggs": {
    "actors": {
      "nested": {
        "path": "actors"
      },
      "aggs": {
        "actor_name": {
          "terms": {
            "field": "actors.first_name",
            "size": 10
          }
        }
      }
    },
    "actor_name": {
      "terms": {
        "field": "actors.first_name"
      }
    }
  }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值