探索ES-嵌套对象和父子对象(四)

2,096 阅读3分钟

前文回顾

之前讲完了探索ES-对象和嵌套对象(三),今天继续深入讲讲父子结构。

嵌套对象

上篇有讲到嵌套对象可以解决数组对象不能关联查询的问题。

但是,嵌套对象也有一些不足之处。

因为ES的文档是不可修改的,所以每次修改了子对象,都需要重新创建一个新的文档对象。这种实现方式会导致增大修改的开销。

那是不是有一种方式可以在修改子对象的时候,不会影响到父对象呢?

下面介绍的父子对象可以解决这个问题。

父子对象

我们先来看一下官网的例子。先来看一下mapping

PUT my_index
{
  "mappings": {
    "_doc": {
      "properties": {
        "my_join_field": { 
          "type": "join",
          "relations": {
            "question": "answer" 
          }
        }
      }
    }
  }}

从上面的mapping中可以看到父子节点的需要join类型来进行关联。与join类型同级别的还有relations属性,设置了父节点的名称和子节点的名称。

让我们看看父节点是如何插入的。

PUT my_index/_doc/1?refresh
{
  "text": "This is a question",
  "my_join_field": {
    "name": "question" 
  }}

PUT my_index/_doc/2?refresh
{
  "text": "This is another question",
  "my_join_field": {
    "name": "question"
  }}

可以看到在插入父节点,需要在my_join_field字段中用name字段来指定。

那么插入子节点呢?

PUT my_index/_doc/3?routing=1&refresh {
  "text": "This is an answer",
  "my_join_field": {
    "name": "answer", 
    "parent": "1" 
  }}

PUT my_index/_doc/4?routing=1&refresh
{
  "text": "This is another answer",
  "my_join_field": {
    "name": "answer",
    "parent": "1"
  }}

可以看到和普通的文档有三点不同。

  1. 需要在join字段中指定name
  2. 需要在join字段中指定parentid
  3. 需要加上routing字段

我们查询一下使用了父子节点的文档。得到如下所示数据。

      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "text" : "This is a question",
          "my_join_field" : {
            "name" : "question"
          }
        }
      },
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_routing" : "1",
        "_source" : {
          "text" : "This is an answer",
          "my_join_field" : {
            "name" : "answer",
            "parent" : "1"
          }
        }
      },

可以看到无论在父节点还是在子节点中都存在一个join类型的字段。 父节点的join类型中包含了name,而子节点的join类型中包含了nameparent

父子节点查询

那么如何查询特定父节点下面的子节点呢?可以使用parent_id查询。

GET my_index/_search
{
  "query": {
    "parent_id": { 
      "type": "answer",
      "id": "1"
    }
  }
}

在上面语句中用type指定了查询的是父节点还是子节点,用id表示需要查询哪一个parent下面的子节点。

得到如下两条记录。

    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.13353139,
        "_routing" : "1",
        "_source" : {
          "text" : "This is an answer",
          "my_join_field" : {
            "name" : "answer",
            "parent" : "1"
          }
        }
      },
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 0.13353139,
        "_routing" : "1",
        "_source" : {
          "text" : "This is another answer",
          "my_join_field" : {
            "name" : "answer",
            "parent" : "1"
          }
        }
      }
    ]

关于写作

以后这里每天都会写一篇文章,题材不限,内容不限,字数不限。尽量把自己每天的思考都放入其中。

如果这篇文章给你带来了一些帮助,可以动动手指点个赞,顺便关注一波就更好了。

如果上面都没有,那么写下读完之后最想说的话?有效的反馈和你的鼓励是对我最大的帮助。

另外打算把博客给重新捡起来了。欢迎大家来访问吃西瓜

我是shane。今天是2019年8月26日。百天写作计划的第三十三天,33/100。