Elasticsearch object nested join 數(shù)據(jù)類型

Object 類型

在設(shè)計(jì)索引mapping時(shí),在某些業(yè)務(wù)下,需要設(shè)計(jì)的對(duì)象中包含對(duì)象,俗稱內(nèi)部對(duì)象,此時(shí)就可以使用Object類型來(lái)存儲(chǔ)對(duì)象.
以下定義了店鋪對(duì)象,包含店鋪名稱、店鋪編碼、供應(yīng)商信息,另外供應(yīng)商信息中又包含供應(yīng)商編碼、供應(yīng)商名稱。同時(shí)供應(yīng)商信息還包含自身的對(duì)象屬性所在區(qū)域,所在區(qū)域又包含省和市,這種定義才能滿足查詢店鋪信息、查詢供應(yīng)商所有店鋪信息,以及查詢某地區(qū)的所有店鋪信息等等場(chǎng)景。

#定義mapping
PUT my_shop_0425
{
  "settings": {
    "index": {
      "number_of_shards": 1,
      "number_of_replicas": 1
    }
  },
  "mappings": {
    "properties": {
      "shopName": {
        "type": "text",
        "analyzer": "ik_smart"
      },
      "shopCode": {
        "type": "keyword"
      },
      "supplier": {
        "properties": {
          "supplier_code": {
            "type": "keyword"
          },
          "supplier_name": {
            "type": "text",
            "analyzer": "ik_smart"
          },
          "area": {
            "properties": {
              "province": {
                "type": "keyword"
              },
              "city": {
                "type": "keyword"
              }
            }
          }
        }
      }
    }
  }
}
#插入測(cè)試數(shù)據(jù)
POST my_shop_0425/_bulk
{"index":{"_id":1}}
{"shopName":"蘋果熱銷店鋪","shopCode":"sc001","supplier":{"supplier_code":"001","supplier_name":"南京農(nóng)村電商領(lǐng)導(dǎo)者","area":{"province":"江蘇省","city":"南京市"}}}
{"index":{"_id":2}}
{"shopName":"美的熱銷店鋪","shopCode":"sc002","supplier":{"supplier_code":"001","supplier_name":"南京農(nóng)村電商領(lǐng)導(dǎo)者","area":{"province":"江蘇省","city":"南京市"}}}
{"index":{"_id":3}}
{"shopName":"金沙酒熱銷店鋪","shopCode":"sc003","supplier":{"supplier_code":"002","supplier_name":"山東農(nóng)村電商領(lǐng)導(dǎo)者","area":{"province":"江蘇省","city":"南京市"}}}
{"index":{"_id":4}}
{"shopName":"華為熱銷店鋪","shopCode":"sc004","supplier":{"supplier_code":"002","supplier_name":"山東農(nóng)村電商領(lǐng)導(dǎo)者","area":{"province":"山東省","city":"青島市"}}}

2家供應(yīng)商
南京農(nóng)村電商領(lǐng)導(dǎo)者 店鋪:蘋果熱銷店鋪+美的熱銷店鋪
山東農(nóng)村電商領(lǐng)導(dǎo)者 店鋪:金沙酒熱銷店鋪+華為熱銷店鋪

查詢供應(yīng)商001對(duì)應(yīng)的所有店鋪:

POST my_shop_0425/_search
{
  "query": {
    "match": {
      "supplier.supplier_code": "001"
    }
  }
}
#返回
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 0.6931471,
    "hits" : [
      {
        "_index" : "my_shop_0425",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.6931471,
        "_source" : {
          "shopName" : "蘋果熱銷店鋪",
          "shopCode" : "sc001",
          "supplier" : {
            "supplier_code" : "001",
            "supplier_name" : "南京農(nóng)村電商領(lǐng)導(dǎo)者",
            "area" : {
              "province" : "江蘇省",
              "city" : "南京市"
            }
          }
        }
      },
      {
        "_index" : "my_shop_0425",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.6931471,
        "_source" : {
          "shopName" : "美的熱銷店鋪",
          "shopCode" : "sc002",
          "supplier" : {
            "supplier_code" : "001",
            "supplier_name" : "南京農(nóng)村電商領(lǐng)導(dǎo)者",
            "area" : {
              "province" : "江蘇省",
              "city" : "南京市"
            }
          }
        }
      }
    ]
  }
}

#查詢銷售區(qū)域在南京的所有店鋪
#查詢銷售區(qū)域在南京的所有店鋪
POST my_shop_0425/_search
{
  "query": {
    "match": {
      "supplier.area.city": "南京市"
    }
  }
}
#返回
{
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 0.35667494,
    "hits" : [
      {
        "_index" : "my_shop_0425",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.35667494,
        "_source" : {
          "shopName" : "蘋果熱銷店鋪",
          "shopCode" : "sc001",
          "supplier" : {
            "supplier_code" : "001",
            "supplier_name" : "南京農(nóng)村電商領(lǐng)導(dǎo)者",
            "area" : {
              "province" : "江蘇省",
              "city" : "南京市"
            }
          }
        }
      },
      {
        "_index" : "my_shop_0425",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.35667494,
        "_source" : {
          "shopName" : "美的熱銷店鋪",
          "shopCode" : "sc002",
          "supplier" : {
            "supplier_code" : "001",
            "supplier_name" : "南京農(nóng)村電商領(lǐng)導(dǎo)者",
            "area" : {
              "province" : "江蘇省",
              "city" : "南京市"
            }
          }
        }
      },
      {
        "_index" : "my_shop_0425",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 0.35667494,
        "_source" : {
          "shopName" : "金沙酒熱銷店鋪",
          "shopCode" : "sc003",
          "supplier" : {
            "supplier_code" : "002",
            "supplier_name" : "山東農(nóng)村電商領(lǐng)導(dǎo)者",
            "area" : {
              "province" : "江蘇省",
              "city" : "南京市"
            }
          }
        }
      }
    ]
  }
}

Join 類型

Join 類型是一種特殊的類型,類似父子結(jié)構(gòu),一個(gè)子文檔只能由一個(gè)父文檔,一個(gè)父文檔可以有多個(gè)子文檔。

#定義索引,my_goods_sale為售賣的上信息,my_goods_comment為商品的評(píng)價(jià)信息
PUT my_goods_hot_sale
{
  "mappings": {
    "properties": {
      "my_id": {
        "type": "keyword"
      },
      "my_join_field": { 
        "type": "join",
        "relations": {
          "my_goods_sale": "my_goods_comment" 
        }
      }
    }
  }
}
#添加商品售賣ID為1的信息
PUT my_goods_hot_sale/_doc/1?refresh
{
  "my_id": "1",
  "text": "This is a my_goods_sale",
  "my_join_field": {
    "name": "my_goods_sale" 
  }
}
#添加商品售賣ID為2的信息
PUT my_goods_hot_sale/_doc/2?refresh
{
  "my_id": "2",
  "text": "This is another my_goods_sale",
  "my_join_field": {
    "name": "my_goods_sale"
  }
}
#添加商品售賣的評(píng)價(jià)3,父商品為1
PUT my_goods_hot_sale/_doc/3?routing=1&refresh
{
  "my_id": "3",
  "text": "This is an comment",
  "my_join_field": {
    "name": "my_goods_comment", 
    "parent": "1" 
  }
}
#添加商品售賣的評(píng)價(jià)4,父商品為1
PUT my_goods_hot_sale/_doc/4?routing=1&refresh
{
  "my_id": "4",
  "text": "This is another comment",
  "my_join_field": {
    "name": "my_goods_comment",
    "parent": "1"
  }
}
  • 根據(jù)父文檔查詢子文檔
GET my_goods_hot_sale/_search
{
  "query": {
    "has_parent": {
      "parent_type": "my_goods_sale",
      "query": {
        "match": {
          "text": "my_goods_sale"
        }
      }
    }
  }
}
  • 根據(jù)子文檔查詢父文檔
GET my_goods_hot_sale/_search
{
  "query": {
    "has_child": {
      "type": "my_goods_comment",
      "query": {
        "match_all": {}
      }
    }
  }
}

Nested 類型

nested 是 object 的專用版本,允許對(duì)象數(shù)組以可以彼此獨(dú)立查詢的方式進(jìn)行索引。
ES 中其實(shí)是沒(méi)有內(nèi)部對(duì)象的概念,因此它將對(duì)象層次結(jié)構(gòu)簡(jiǎn)化為字段名稱和值,以列表的形式展現(xiàn)。
首先來(lái)比較 nester 與 parent/child 以及 Object 的區(qū)別


對(duì)比.png

以 B2B 電商行業(yè)的實(shí)際業(yè)務(wù)場(chǎng)景來(lái)舉例說(shuō)明,2B 行業(yè)的交易具有一定封閉性,只有簽署合同、經(jīng)常往來(lái)交易的會(huì)員往往有更高資格的交易權(quán)、議價(jià)權(quán)。
定義商品索引,其中 groupPrice 標(biāo)識(shí)分組價(jià)對(duì)象,對(duì)象里面包含了 boxLevelPrice 分組價(jià)格、level 分組級(jí)別,當(dāng)前端業(yè)務(wù)線搜索時(shí),傳入用戶所在組級(jí)別,即可查詢對(duì)應(yīng)的價(jià)格。為了便于區(qū)分我們先定義為 Object 類型來(lái)觀察下現(xiàn)象:

定義分組為 Object 類型

PUT goods_info_object
{
  "mappings": {
    "properties": {
      "goodsName": {
        "type": "text",
        "analyzer": "ik_smart"
      },
      "skuCode": {
        "type": "keyword"
      },
      "brandName": {
        "type": "keyword"
      },
      "shopCode": {
        "type": "keyword"
      },
      "publicPrice": {
        "type": "float"
      },
      "groupPrice": {
        "properties": {
          "boxLevelPrice": {
            "type": "keyword"
          },
          "level": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

#插入測(cè)試數(shù)據(jù)
POST goods_info_object/_bulk
{"index":{"_id":1}}
{"goodsName":"美國(guó)蘋果","skuCode":"skuCode1","brandName":"美國(guó)蘋果","shopCode":"sc00001","publicPrice":"8388.88","groupPrice":[{"boxLevelPrice":"4888.00","level":"A"},{"boxLevelPrice":"6888.00","level":"B"}]}
{"index":{"_id":2}}
{"goodsName":"山東蘋果","skuCode":"skuCode2","brandName":"山東蘋果","shopCode":"sc00001","publicPrice":"7388.88","groupPrice":[{"boxLevelPrice":"5888.00","level":"A"},{"boxLevelPrice":"4888.00","level":"B"}]}

#檢索A組且價(jià)格等于4888.00的商品
POST goods_info_object/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "groupPrice.level": "A"
          }
        },
        {
          "match": {
            "groupPrice.boxLevelPrice": "4888.00"
          }
        }
      ]
    }
  }
}

#返回:
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 0.45840856,
    "hits" : [
      {
        "_index" : "goods_info_object",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.45840856,
        "_source" : {
          "goodsName" : "美國(guó)蘋果",
          "skuCode" : "skuCode1",
          "brandName" : "美國(guó)蘋果",
          "shopCode" : "sc00001",
          "publicPrice" : "8388.88",
          "groupPrice" : [
            {
              "boxLevelPrice" : "4888.00",
              "level" : "A"
            },
            {
              "boxLevelPrice" : "6888.00",
              "level" : "B"
            }
          ]
        }
      },
      {
        "_index" : "goods_info_object",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.45840856,
        "_source" : {
          "goodsName" : "山東蘋果",
          "skuCode" : "skuCode2",
          "brandName" : "山東蘋果",
          "shopCode" : "sc00001",
          "publicPrice" : "7388.88",
          "groupPrice" : [
            {
              "boxLevelPrice" : "5888.00",
              "level" : "A"
            },
            {
              "boxLevelPrice" : "4888.00",
              "level" : "B"
            }
          ]
        }
      }
    ]
  }
}

顯然返回的數(shù)據(jù)不是我們期望的,這是因?yàn)?ES 中將 Object 數(shù)組打平了做存儲(chǔ)導(dǎo)致

定義分組為 Nested 類型

PUT goods_info_nested
{
  "mappings": {
    "properties": {
      "goodsName": {
        "type": "text",
        "analyzer": "ik_smart"
      },
      "skuCode": {
        "type": "keyword"
      },
      "brandName": {
        "type": "keyword"
      },
      "shopCode": {
        "type": "keyword"
      },
      "publicPrice": {
        "type": "float"
      },
      "groupPrice": {
        "type": "nested",
        "properties": {
          "boxLevelPrice": {
            "type": "keyword"
          },
          "level": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

#插入同樣的測(cè)試數(shù)據(jù)
POST goods_info_nested/_bulk
{"index":{"_id":1}}
{"goodsName":"美國(guó)蘋果","skuCode":"skuCode1","brandName":"美國(guó)蘋果","shopCode":"sc00001","publicPrice":"8388.88","groupPrice":[{"boxLevelPrice":"4888.00","level":"A"},{"boxLevelPrice":"6888.00","level":"B"}]}
{"index":{"_id":2}}
{"goodsName":"山東蘋果","skuCode":"skuCode2","brandName":"山東蘋果","shopCode":"sc00001","publicPrice":"7388.88","groupPrice":[{"boxLevelPrice":"5888.00","level":"A"},{"boxLevelPrice":"4888.00","level":"B"}]}
#查詢
POST goods_info_nested/_search
{
  "query": {
    "nested": {
      "path": "groupPrice",
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "groupPrice.level": "A"
              }
            },
            {
              "match": {
                "groupPrice.boxLevelPrice": "4888.00"
              }
            }
          ]
        }
      }
    }
  }
}
#返回:
"hits" : [
      {
        "_index" : "goods_info_nested",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.3862942,
        "_source" : {
          "goodsName" : "美國(guó)蘋果",
          "skuCode" : "skuCode1",
          "brandName" : "美國(guó)蘋果",
          "shopCode" : "sc00001",
          "publicPrice" : "8388.88",
          "groupPrice" : [
            {
              "boxLevelPrice" : "4888.00",
              "level" : "A"
            },
            {
              "boxLevelPrice" : "6888.00",
              "level" : "B"
            }
          ]
        }
      }
    ]

返回的是我們期望的,說(shuō)明 nested 查詢生效,解決了嵌套查詢的問(wèn)題

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容