当前位置:   article > 正文

es 嵌套对象查询_es嵌套查询

es嵌套查询

基础环境
嵌套查询的问题

下面的例子通过 PUT order 创建表结构,POST order/_doc/10001 填充表数据,goods 使用 es的自动类型推断,且是由多个对象组成
GET order/_search是想要获取 goods中 包含 {"name":"当归","num":5}的数据,正常应该是没有的,但是结果却查出来了

PUT order
{
  "mappings": {
    "properties": {
      "id":{
        "type": "keyword"
      },
      "type":{
        "type": "text"
      }
    }
  }
}

POST order/_doc/10001
{
  "id":10001,
  "type":"changfan",
  "goods":[
     {
       "id":1,
       "name":"当归",
       "price":102,
       "num":1
     },
     {
       "id":1,
       "name":"人参",
       "price":102,
       "num":5
     }
  ]
}

GET order/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "goods.num": {
              "value": 5
            }
          }
        },{
          "match_phrase": {
            "goods.name": "当归"
          }
        }
      ]
    }
  }
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

这种嵌套数据在es中是下面的存储格式

{
  "goods.name":["当归","人参"],
  "goods.num":[1,5]
}
  • 1
  • 2
  • 3
  • 4
使用 nested 类型

nested 类型用于处理嵌套的文档结构,其中一个文档中包含了另一个文档的数组。
将需要嵌套查询的字段设置为nested

PUT order2
{
  "mappings": {
    "properties": {
      "id":{
        "type": "keyword"
      },
      "type":{
        "type": "text"
      },
      "goods":{
        "type": "nested"
      }
    }
  }
}

POST order2/_doc/10001
{
  "id":10001,
  "type":"changfan",
  "goods":[
     {
       "id":1,
       "name":"当归",
       "price":102,
       "num":1
     },
     {
       "id":1, 
       "name":"人参",
       "price":102,
       "num":5
     }
  ]
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

使用 nested 进行查询
在普通的查询中 增加了 nested属性,其中path 指对那个属性进行嵌套查询,这个就解决了嵌套查询的问题

GET order2/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "goods",
            "query": {
              "bool": {
                "must": [
                  {
                    "term": {
                      "goods.num": {
                        "value": 1
                      }
                    }
                  },
                  {
                    "match_phrase": {
                      "goods.name": "当归"
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
join
  • join 在 mapping 中指定了父子文档的关系
  • 有了关系就可以使用 has 查询,类似于 ORM框架 的 whereHas 过滤
  • join 获取嵌套数据不像 nested 能够一次性取出

指定了goods的类型为 join, 关联关系为父子

PUT order3
{
  "mappings": {
    "properties": {
      "id":{
        "type": "keyword"
      },
      "type":{
        "type": "text"
      },
      "goods":{
        "type": "join",
         "relations":{
           "parent":"child"
         }
      }
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

创建父文档

POST order3/_doc/10001
{
  "id":10001,
  "type":"changfan",
  "goods":{
    "name":"parent"
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

创建子文档

POST order3/_doc/10001-1?routing=10001
{
  "goods":{
    "name":"child",
    "parent":10001
  },
  "id": 1,
  "name": "当归",
  "price": 102,
  "num": 1
}

POST order3/_doc/10001-2?routing=10001
{
  "goods": {
    "name": "child",
    "parent": 10001
  },
  "id": 2,
  "name": "人参",
  "price": 102,
  "num": 5
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

使用 has_child 查出符合条件的父文档

GET order3/_search
{
  "query": {
    "has_child": {
      "type": "child",
      "query": {
        "bool": {
          "must": [
            {
              "term": {
                "num": {
                  "value": 1
                }
              }
            },
            {
              "match_phrase": {
                "name": "当归"
              }
            }
          ]
        }
      }
    }
  }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

image.png
直接通过父文档id查询子文档信息

GET order3/_search
{
  "query": {
    "parent_id":{
      "type":"child",
      "id":10001
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

image.png
或者通过 has_parent 来反查

GET order3/_search
{
  "query": {
    "has_parent": {
      "parent_type": "parent",
      "query": {
        "term": {
          "id": {
            "value": 10001
          }
        }
      }
    }
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

image.png

nested vs join
nestedjoin
优点读取更快父子可以单独更新,不相互影响
缺点不像join可以父子单独更新,只要更新,就全部受影响由于父子分开,读取性能比 nested 差
常用场景查多写少,需要获取全部子文档子文档数量多,且更新频繁
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/456810
推荐阅读
相关标签
  

闽ICP备14008679号