白话Elasticsearch58-数据建模实战_基于nested object实现博客与评论嵌套关系

2021-08-17 15:06:17 浏览数 (1)


概述

继续跟中华石杉老师学习ES,第58篇

课程地址: https://www.roncoo.com/view/55


官网

Nested datatype:戳这里

Object datatype:戳这里


示例

Object datatype

让ES自动创建索引,插入一条数据

代码语言:javascript复制
#让ES自动创建索引,插入一条数据
PUT /website/blogs/1
{
  "title": "花无缺发表的一篇帖子",
  "content": "我是花无缺,大家要不要考虑一下投资房产和买股票的事情啊。。。",
  "tags": [
    "投资",
    "理财"
  ],
  "comments": [
    {
      "name": "小鱼儿",
      "comment": "什么股票啊?推荐一下呗",
      "age": 28,
      "stars": 4,
      "date": "2016-09-01"
    },
    {
      "name": "黄药师",
      "comment": "我喜欢投资房产,风,险大收益也大",
      "age": 31,
      "stars": 5,
      "date": "2016-10-22"
    }
  ]
}

查看mapping

代码语言:javascript复制
GET /website/_mapping/blogs/

返回:

代码语言:javascript复制
{
  "website": {
    "mappings": {
      "blogs": {
        "properties": {
          "comments": {
            "properties": {
              "age": {
                "type": "long"
              },
              "comment": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              },
              "date": {
                "type": "date"
              },
              "name": {
                "type": "text",
                "fields": {
                  "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                  }
                }
              },
              "stars": {
                "type": "long"
              }
            }
          },
          "content": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "tags": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "title": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    }
  }
}

需求: 被年龄是28岁的黄药师评论过的博客

代码语言:javascript复制
#被年龄是28岁的黄药师评论过的博客
GET /website/blogs/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "comments.name": "黄药师"
          }
        },
        {
          "match": {
            "comments.age": 28
          }
        }
      ]
    }
  }
}

返回:


查询结果不对原因分析

官方文档: 戳这里

归根到底 还是object类型数据结构的底层存储导致的查询不正确

代码语言:javascript复制
{
  "title":            [ "花无缺", "发表", "一篇", "帖子" ],
  "content":             [ "我", "是", "花无缺", "大家", "要不要", "考虑", "一下", "投资", "房产", "买", "股票", "事情" ],
  "tags":             [ "投资", "理财" ],
  "comments.name":    [ "小鱼儿", "黄药师" ],
  "comments.comment": [ "什么", "股票", "推荐", "我", "喜欢", "投资", "房产", "风险", "收益", "大" ],
  "comments.age":     [ 28, 31 ],
  "comments.stars":   [ 4, 5 ],
  "comments.date":    [ 2016-09-01, 2016-10-22 ]
}

object类型底层数据结构,会将一个json数组中的数据,进行扁平化

所以,直接命中了这个document,name=黄药师,age=28,在范围之内,正好符合,所以被查询出来了。


Nested datatype

解决object查询不对的问题

引入nested object类型,来解决object类型底层数据结构导致的问题


修改mapping,将comments的类型从object设置为nested

修改mapping,将comments的类型从object设置为nested

代码语言:javascript复制
DELETE website


PUT /website
{
  "mappings": {
    "blogs": {
      "properties": {
        "comments": {
          "type": "nested", 
          "properties": {
            "name":    { "type": "text"  },
            "comment": { "type": "text"  },
            "age":     { "type": "short"   },
            "stars":   { "type": "short"   },
            "date":    { "type": "date"    }
          }
        }
      }
    }
  }
}

写入数据

代码语言:javascript复制
PUT /website/blogs/1
{
  "title": "花无缺发表的一篇帖子",
  "content":  "我是花无缺,大家要不要考虑一下投资房产和买股票的事情啊。。。",
  "tags":  [ "投资", "理财" ],
  "comments": [ 
    {
      "name":    "小鱼儿",
      "comment": "什么股票啊?推荐一下呗",
      "age":     28,
      "stars":   4,
      "date":    "2016-09-01"
    },
    {
      "name":    "黄药师",
      "comment": "我喜欢投资房产,风,险大收益也大",
      "age":     31,
      "stars":   5,
      "date":    "2016-10-22"
    }
  ]
}

查看mapping

代码语言:javascript复制
#查看mapping
GET /website/_mapping/blogs/

返回:

代码语言:javascript复制
{
  "website": {
    "mappings": {
      "blogs": {
        "properties": {
          "comments": {
            "type": "nested",
            "properties": {
              "age": {
                "type": "short"
              },
              "comment": {
                "type": "text"
              },
              "date": {
                "type": "date"
              },
              "name": {
                "type": "text"
              },
              "stars": {
                "type": "short"
              }
            }
          },
          "content": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "tags": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "title": {
            "type": "text",
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    }
  }
}

nested object 存储形式

这样的话,nested object 存储如下:

代码语言:javascript复制
{ 
  "comments.name":    [ "小鱼儿" ],
  "comments.comment": [ "什么", "股票", "推荐" ],
  "comments.age":     [ 28 ],
  "comments.stars":   [ 4 ],
  "comments.date":    [ 2014-09-01 ]
}
{ 
  "comments.name":    [ "黄药师" ],
  "comments.comment": [ "我", "喜欢", "投资", "房产", "风险", "收益", "大" ],
  "comments.age":     [ 31 ],
  "comments.stars":   [ 5 ],
  "comments.date":    [ 2014-10-22 ]
}
{ 
  "title":            [ "花无缺", "发表", "一篇", "帖子" ],
  "body":             [ "我", "是", "花无缺", "大家", "要不要", "考虑", "一下", "投资", "房产", "买", "股票", "事情" ],
  "tags":             [ "投资", "理财" ]
}

再次查询

代码语言:javascript复制
GET /website/blogs/_search 
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "title": "花无缺"
          }
        },
        {
          "nested": {
            "path": "comments",
            "query": {
              "bool": {
                "must": [
                  {
                    "match": {
                      "comments.name": "黄药师"
                    }
                  },
                  {
                    "match": {
                      "comments.age": 28
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}

改成31的呢


score_mode

score_mode:max,min,avg,none,默认是avg

如果搜索命中了多个nested document,如何把多个nested document的分数合并为一个分数


limits on nested mappings and objects

0 人点赞