寫在前面
本文看下es的nested嵌套對象相關內(nèi)容。
1:es用了啥范式?
在關系型數(shù)據(jù)庫中定義了6大數(shù)據(jù)庫范式,即1,2,3,BC,4,5的NF(normal form),分別如下:
1NF:每個列都不可拆分,即都是原子的
2NF:在滿足1NF的基礎上,消除部分函數(shù)依賴
3NF:在滿足2NF的基礎上,消除傳遞函數(shù)依賴
BCNF:在滿足3NF的基礎上,消除主屬性對于碼的部分函數(shù)依賴和傳遞函數(shù)依賴(此時和非主鍵列沒有關系)
4NF:在滿足BCNF的基礎上,消除表內(nèi)的多對多關系
5NF:略
數(shù)據(jù)庫范式的目的在于減少更新的復雜度,以及降低磁盤的存儲空間。其中對于第二個問題存儲設備目前非常廉價而且容量很大,所以不是什么問題了。對于第一個更新的復雜度問題會帶來的查詢效率變低的問題,因為需要更多的關聯(lián)join。那么對于es來說它是使用了哪種范式呢?因為es的設計目標是快速查詢
,所以使用到是反范式
,即冗余存儲
。比如如下的數(shù)據(jù):
如果按照關系型數(shù)據(jù)庫范式來設計,user的信息需要存儲到單獨的一張表中去,但是在es中就是在一個對象中來存儲,對于這種存儲,es支持非常方便和高效的查詢:
- 準備數(shù)據(jù)
DELETE blog
# 設置blog的 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"
}
}
- 查詢
# 查詢 Blog 信息
POST blog/_search
{
"query": {
"bool": {
"must": [
{"match": {"content": "Elasticsearch"}},
{"match": {"user.username": "Jack"}}
]
}
}
}
我們再來看一個存儲對象數(shù)組的例子:
- 準備數(shù)據(jù)
DELETE my_movies
# 電影的Mapping信息
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"
}
]
}
- 查詢first_name為Keanu并且last_name為Hopper的文檔信息
POST my_movies/_search
{
"query": {
"bool": {
"must": [
{"match": {"actors.first_name": "Keanu"}},
{"match": {"actors.last_name": "Hopper"}}
]
}
}
}
按照正常思維,應該查不到才對,但為什么查到了呢?這和es的數(shù)據(jù)存儲方式有關系,對于數(shù)組es默認是按照一種扁平結構來存儲的,如下:
這種存儲結構的好處是可以加快查詢的速度,但壞處呢就是上例中反直覺結果。
所以如果能夠讓內(nèi)部的對象也按照單獨文檔來存儲,就能解決這個查詢錯誤的問題了,而想要使用單獨的文檔來存儲內(nèi)部的對象,就需要用到es提供的nested對象功能,繼續(xù)來看(作為本文的主題,必須單開一部分,還必須是一級標題??????)
。
2:nested對象
nested是一種定義對象的數(shù)據(jù)類型,比如可通過如下方式來定義一個nested的類型:
在保存時會被保存為單獨的文檔,查詢時通過join的方式來查詢,當然此時會犧牲掉部分查詢性能。
- 創(chuàng)建如下的mapping
DELETE my_movies
# 創(chuàng)建 Nested 對象 Mapping
PUT my_movies
{
"mappings" : {
"properties" : {
"actors" : {
"type": "nested",
"properties" : {
"first_name" : {"type" : "keyword"},
"last_name" : {"type" : "keyword"}
}},
"title" : {
"type" : "text",
"fields" : {"keyword":{"type":"keyword","ignore_above":256}}
}
}
}
}
- 接著來插入測試數(shù)據(jù)
POST my_movies/_doc/1
{
"title":"Speed",
"actors":[
{
"first_name":"Keanu",
"last_name":"Reeves"
},
{
"first_name":"Dennis",
"last_name":"Hopper"
}
]
}
此時存儲結構為紅框中所示:
- 查詢first_name為Keanu并且last_name為Hopper的文檔信息
此時就查詢不到了:
POST my_movies/_search
{
"query": {
"bool": {
"must": [
{
"nested": {
"path": "actors",
"query": {
"bool": {
"must": [
{
"match": {
"actors.first_name": "Keanu"
}
},
{
"match": {
"actors.last_name": "Hopper"
}
}
]
}
}
}
}
]
}
}
}
當然如果把"actors.last_name": "Hopper"改為Reeves是能查出來數(shù)據(jù)的:文章來源:http://www.zghlxwxcb.cn/news/detail-844111.html
寫在后面
參考文章列表
關系型數(shù)據(jù)庫MySQL及其優(yōu)化 。文章來源地址http://www.zghlxwxcb.cn/news/detail-844111.html
到了這里,關于ElasticSearch之Nested對象的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!