自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一文帶你掌握Elasticsearch復(fù)合字段類型:Array、Flattened、Nested在業(yè)務(wù)系統(tǒng)中最佳實踐

開發(fā) 前端
elasticsearch 是一個分布式、實時的搜索和分析引擎,通常用于處理和查詢大規(guī)模的結(jié)構(gòu)化與非結(jié)構(gòu)化數(shù)據(jù)。它基于 Apache Lucene 構(gòu)建,具有高效的全文搜索、數(shù)據(jù)存儲、數(shù)據(jù)分析和數(shù)據(jù)可視化功能。elasticsearch 主要應(yīng)用于日志分析、監(jiān)控、數(shù)據(jù)檢索、實時分析等場景。

1.概述

elasticsearch在當下互聯(lián)網(wǎng)系統(tǒng)中使用非常廣泛,是一個非常熱門的組件框架。那elasticsearch到底是什么呢?

elasticsearch 是一個分布式、實時的搜索和分析引擎,通常用于處理和查詢大規(guī)模的結(jié)構(gòu)化與非結(jié)構(gòu)化數(shù)據(jù)。它基于 Apache Lucene 構(gòu)建,具有高效的全文搜索、數(shù)據(jù)存儲、數(shù)據(jù)分析和數(shù)據(jù)可視化功能。elasticsearch 主要應(yīng)用于日志分析、監(jiān)控、數(shù)據(jù)檢索、實時分析等場景。

官方文檔地址:https://www.elastic.co/

2.映射mapping

在 elasticsearch 中,mapping(映射)是指為索引中的字段定義結(jié)構(gòu)、類型和規(guī)則。類似于關(guān)系型數(shù)據(jù)庫中的表結(jié)構(gòu),映射決定了 elasticsearch 如何存儲和索引數(shù)據(jù),其作用和關(guān)系型數(shù)據(jù)庫定義表字段差不多:

定義字段類型:例如字符串、數(shù)字、日期等。

控制字段行為:決定字段是否進行分詞、是否索引、如何排序等。

優(yōu)化查詢性能:正確的映射能提高查詢效率,減少不必要的存儲。

數(shù)據(jù)驗證:映射可以確保寫入的文檔符合預(yù)期的數(shù)據(jù)結(jié)構(gòu)和類型。

映射mapping分為:動態(tài)映射和靜態(tài)映射

2.1 動態(tài)映射

顧名思義,就是自動創(chuàng)建出來的映射。es 根據(jù)存入的文檔,自動分析出來文檔中字段的類型以及存儲方式,這種就是動態(tài)映射。示例如下所示:

首先,先定義一個索引,名為user_info

PUT user_info

一個簡單的DSL語句就建立了一個索引,不太清楚的先跳轉(zhuǎn)上面的鏈接入門學習下哈。

緊接著我們直接插入一條es文檔數(shù)據(jù)

PUT user_info/_doc/1
{
  "id":1,
  "name":"張三",
  "amount":88.99
}

插入成功,再來看看索引user_info的mapping定義:

GET user_info/_mapping

查詢結(jié)果如下:

{
  "user_info" : {
    "mappings" : {
      "properties" : {
        "amount" : {
          "type" : "float"
        },
        "id" : {
          "type" : "long"
        },
        "name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    }
  }
}

可以看到,es在我們插入文檔數(shù)據(jù)時自動檢測字段類型動態(tài)定義了mapping結(jié)構(gòu)。

2.2 靜態(tài)映射

靜態(tài)映射就和關(guān)系型數(shù)據(jù)庫表結(jié)構(gòu)加字段一樣,在插入es文檔數(shù)據(jù)之前,先定義字段mapping再插入數(shù)據(jù),比如我們往user_info添加一個身份證號idCard:

PUT user_info/_mapping
{
  "properties": {
     "idCard": {
      "type": "keyword"
    }
  }
}

keyword關(guān)鍵字類型代表不分詞,elasticsearch會對text字段進行分詞實現(xiàn)全文檢索,但是身份證并不需要分詞,它是一個整體屬性字段,如果是通過動態(tài)映射生成mapping定義,那么會和上面的name字段一樣:

"idCard" : {
      "type" : "text",
      "fields" : {
        "keyword" : {
          "type" : "keyword",
          "ignore_above" : 256
        }
      }
    }

這里我解釋一下這個mapping的定義:其中既包含 text 類型字段用于全文搜索,也包含 keyword 字段用于精確匹配和聚合。這種設(shè)計方式可以在同一個字段上實現(xiàn)不同類型的查詢

text 類型用于全文搜索(如 matchQuery),Elasticsearch 會對 text 類型字段進行分詞(默認使用標準分詞器)。

keyword是這是 idCard 字段的子字段類型,用于精確匹配和聚合。

keyword 類型的字段不會被分詞,適合存儲如ID、狀態(tài)、標簽等字符串數(shù)據(jù)。

**ignore_above: 256**:如果字段的長度超過 256 個字符,將會被忽略,不會被索引

這種組合讓你可以在同一個字段上支持全文搜索和精確匹配,從而滿足不同查詢需求。但實際上name字段也是并不需要分詞的,直接定義keyword更加合理,性能更好。分詞是一個相對比較耗費性能的操作。

由此可見動態(tài)映射也并不是萬能可行的,我個人建議是:

我們在創(chuàng)建真正索引之前,可以先隨便創(chuàng)建一個測試索引,然后寫入測試的es文檔數(shù)據(jù),然后查看測試索引生成的mapping,這樣后面我們在創(chuàng)建真正索引設(shè)置mapping時,就可以在前面得到的mapping基礎(chǔ)上修改,不需要從無到有一個一個字段地開始寫mapping,極大提高效率。如果是往索引添加新字段時,我覺得還是嚴格按照和關(guān)系型數(shù)據(jù)庫表結(jié)構(gòu)加字段一樣,采用靜態(tài)映射插入數(shù)據(jù)前,先手動添加字段mapping定義,杜絕動態(tài)映射帶來的類型不匹配、性能降低等問題。

3.使用數(shù)組Array實現(xiàn)一對多查詢

在平時業(yè)務(wù)系統(tǒng)表單列表搜索中,一對多查詢是非常常見的,比如說,一個用戶有多個標簽,有多個角色,這時候我們會搜索某些標簽或者某些角色下有哪些用戶,是不是很常見呀???話不多說開干,我這里以標簽展示,首先我們按照建議先通過靜態(tài)映射在索引user_info中添加一個新字段tag存儲標簽id:

PUT user_info/_mapping
{
  "properties": {
     "tag": {
      "type": "long"
    }
  }
}

接下來我們就可以插入數(shù)據(jù)了。這時候你可能會問,你這個定義tag字段是long類型,并沒有定義array類型呀???這就可以插入數(shù)組多個數(shù)據(jù)了?是的,elasticsearch關(guān)于mapping字段介紹時,明確提到你無需專門聲明某字段為數(shù)組類型,任何字段都可以隱式地存儲為數(shù)組。但是要求數(shù)組中的所有值必須具有相同的數(shù)據(jù)類型。不支持混合數(shù)據(jù)類型的數(shù)組: [10,“ some string”],插入數(shù)據(jù)示例:

PUT user_info/_doc/10
{
  "id":10,
  "name":"張三2",
  "tag":[1,2,3] 
}

PUT user_info/_doc/11
{
  "id":11,
  "name":"張三3",
  "tag":[3,4] 
}
PUT user_info/_doc/12
{
  "id":12,
  "name":"張三4",
  "tag":[4,8,9] 
}

PUT user_info/_doc/13
{
  "id":13,
  "name":"張三5",
  "tag":[1,6] 
}

然后我們來搜索試試吧,搜索有標簽id為3或者4的用戶:

GET user_info/_search
{
  "query": {
    "terms": {
      "tag": [3,4]
    }
  }
}

查詢結(jié)果id=10,11,12都命中了。

Java查詢實現(xiàn)代碼:

boolQueryBuilder.must(QueryBuilders.termsQuery("tag", tagIds));

關(guān)于Spring Boot整合restHighLevelClient實現(xiàn)es相關(guān)操作,請查看上面的入門篇

如果要查詢同時包含標簽id為3和4的員工:

GET user_info/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "tag": {
              "value": 3
            }
          }
        },
        {
          "term": {
            "tag": {
              "value": 4
            }
          }
        }
      ]
    }
  }
}

只命中id=11這一條數(shù)據(jù)

Java實現(xiàn)代碼:

for(tagId : tagIds) {
  boolQueryBuilder.must(QueryBuilders.termQuery("tag", tagId));
}

數(shù)組Array的限制:無法建立數(shù)組元素之間的關(guān)系

PUT orders/_doc/1
{
  "products": ["laptop", "mouse"],
  "quantities": [1, 2]
}

假設(shè)你想查詢購買了 "laptop" 且數(shù)量為 1 的訂單。這在 Elasticsearch 的數(shù)組查詢中無法實現(xiàn),因為 Elasticsearch 無法判斷 "laptop" 和 1 是相關(guān)聯(lián)的(它們只被視為兩個獨立的數(shù)組字段)。

解決方案:如果你需要這種關(guān)聯(lián)關(guān)系,應(yīng)使用 nested 類型來代替數(shù)組字段。后面會講。

總的來說,數(shù)組(Arrays)字段類型適用于簡單的多值字段,如標簽、興趣、角色等場景。使用簡單、查詢高效、

項目推薦:基于SpringBoot2.x、SpringCloud和SpringCloudAlibaba企業(yè)級系統(tǒng)架構(gòu)底層框架封裝,解決業(yè)務(wù)開發(fā)時常見的非功能性需求,防止重復(fù)造輪子,方便業(yè)務(wù)快速開發(fā)和企業(yè)技術(shù)棧框架統(tǒng)一管理。引入組件化的思想實現(xiàn)高內(nèi)聚低耦合并且高度可配置化,做到可插拔。嚴格控制包依賴和統(tǒng)一版本管理,做到最少化依賴。

4.使用Flattened存儲動態(tài)字段

Flattened 類型是 Elasticsearch 7.3 引入的一種特殊的字段類型,主要用于處理層級結(jié)構(gòu)(嵌套結(jié)構(gòu))數(shù)據(jù),但以扁平化方式存儲,以節(jié)省內(nèi)存并提高查詢效率。它特別適用于存儲動態(tài)的或高可變的鍵值對數(shù)據(jù),例如日志、自定義字段等。

該類型會將嵌套 JSON 對象的鍵值扁平化為單一層級字段。開搞?。。∠榷ㄒ粋€字段存儲用戶附加信息:

PUT user_info/_mapping
{
  "properties": {
      "extendInfo": {
        "type": "flattened"
      }
    }
}

插入數(shù)據(jù),我們在上面的數(shù)據(jù)更新字段extendInfo信息:

POST user_info/_update/10
{
  "doc":{
    "extendInfo":{
      "age":18,
      "gender":"女",
      "height":180,
      "weight":"68kg"
    }
  }
}

POST user_info/_update/11
{
  "doc":{
    "extendInfo":{
      "age":30,
      "gender":"女"
    }
  }
}

POST user_info/_update/12
{
  "doc":{
    "extendInfo":{
      "height":170,
      "weight":"58kg",
      "hobby":"籃球"
    }
  }
}

POST user_info/_update/13
{
  "doc":{
    "extendInfo":{
      "address":"杭州",
      "phone":"12334464"
    }
  }
}

可以看到我們插入的extendInfo的信息都不太一樣,主打就是一個動態(tài)字段信息。接下來查詢看看:

GET user_info/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "extendInfo.gender": {
              "value": "女"
            }
          }
        },
        {
          "term": {
            "extendInfo.age": {
              "value": 18
            }
          }
        }
      ]
    }
  }
}

查詢結(jié)果會命中id=10這條數(shù)據(jù)

flattened 類型是一種折中的選擇,適合存儲動態(tài)鍵值對數(shù)據(jù),如日志、標簽和指標等。它提供了比 object 類型更好的性能,并且比 nested 類型占用更少的資源。然而,它無法進行復(fù)雜的嵌套關(guān)聯(lián)查詢和深層聚合,因此需要根據(jù)業(yè)務(wù)需求進行合理選擇。

5.使用Nested存儲對象數(shù)組

Nested:嵌套類型,有點千呼萬喚始出來的感覺,他到底能干嘛呢?

nested 類型允許 Elasticsearch 以“獨立文檔”方式存儲每個嵌套對象,并維持每個對象內(nèi)字段之間的關(guān)系。這樣可以確保查詢到的數(shù)據(jù)和文檔結(jié)構(gòu)一致,避免出現(xiàn)跨對象匹配的情況。

上面我們提到數(shù)據(jù)Array類型的限制是無法建立兩個數(shù)組字段直接的關(guān)系,而Flattened是存儲一個對象動態(tài)字段,Nested就是可以存儲數(shù)據(jù)對象,并能維護數(shù)組對象之間關(guān)系,來看看示例,一個用戶有多個家人family:

PUT user_info/_mapping
{
  "properties": {
      "family": {
        "type": "nested"
      }
    }
}

寫入數(shù)據(jù),基于上面的數(shù)據(jù)寫入family即可:

POST user_info/_update/10
{
  "doc":{
    "family":[
      {
        "name":"李四",
        "relation":"父子",
        "amount":10000
      },
      {
        "name":"王婆",
        "relation":"母子",
        "amount":6000
      }
    ]
  }
}

POST user_info/_update/11
{
  "doc":{
    "family":[
      {
        "name":"李四",
        "relation":"兄弟",
        "amount":10000
      },
      {
        "name":"小紅",
        "relation":"夫妻",
        "amount":1000
      }
    ]
  }
}

POST user_info/_update/12
{
  "doc":{
    "family":[
      {
        "name":"王五",
        "relation":"父子",
        "amount":10000
      },
      {
        "name":"小蘭",
        "relation":"兄妹",
        "amount":1000
      }
    ]
  }
}

接下來我們查詢 relation=父子 and amount=10000的數(shù)據(jù):

GET user_info/_search
{
  "query": {
    "nested": {
      "path": "family",
      "query": {
        "bool": {
          "must": [
            {
              "term": {
                "family.relation.keyword": {
                  "value": "父子"
                }
              }
            },
            {
              "term": {
                "family.amount": {
                  "value": 10000
                }
              }
            }
          ]
        }
      }
    }
  }
}

查詢結(jié)果命中了id=10,12兩條數(shù)據(jù)。你可能注意到查詢family.relation后面接了keyword,這是因為我們嵌套字段對象屬性是動態(tài)生成的,family.relation自動映射成text,對text字段進行term精確匹配,必須接上關(guān)鍵字keyword

nested 類型在存儲和查詢時比普通 Flattened 類型更耗資源,因為每個嵌套對象會被當作單獨文檔存儲和索引,并且文檔不能直接更新嵌套對象的部分字段,通常需要重建整個嵌套對象。

nested 類型適合嵌套對象數(shù)組的結(jié)構(gòu)化數(shù)據(jù),支持精確的對象內(nèi)匹配查詢和聚合。當嵌套對象只需要簡單查詢、沒有嚴格的對象內(nèi)關(guān)聯(lián)需求時,使用 Flattened 類型更高效。

6.總結(jié)

上面我們講了各自的定義、使用、局限性,最后這里總結(jié)概括下:

字段類型

適用場景

優(yōu)點

缺點

Array

適合簡單的多值字段(如標簽、愛好)

易用、性能好

無法維護元素之間的關(guān)系

Flattened

動態(tài)鍵值對結(jié)構(gòu)(如可變的配置、元數(shù)據(jù))

占用存儲空間少、動態(tài)字段支持好

不支持嵌套關(guān)系查詢

Nested

多層級結(jié)構(gòu)對象,且需要查詢對象內(nèi)部關(guān)系

支持復(fù)雜的關(guān)系查詢

性能和存儲開銷大

簡單來說:

  • Array 簡單快捷,適合不需要關(guān)系的多值字段。
  • Flattened 提供了一種高效存儲動態(tài)鍵值對的方式,但不適合復(fù)雜查詢。
  • Nested 適合復(fù)雜的嵌套關(guān)系查詢,但會增加存儲和查詢的開銷。

根據(jù)你的業(yè)務(wù)需求,合理選擇字段類型可以顯著提升系統(tǒng)的查詢性能和數(shù)據(jù)管理效率。

責任編輯:武曉燕 來源: Shepherd進階筆記
相關(guān)推薦

2023-12-21 17:11:21

Containerd管理工具命令行

2022-12-20 07:39:46

2023-12-15 09:45:21

阻塞接口

2022-02-18 10:13:07

SolrElasticSea開源

2021-02-22 09:05:59

Linux字符設(shè)備架構(gòu)

2021-06-04 09:35:05

Linux字符設(shè)備架構(gòu)

2020-12-18 11:54:22

Linux系統(tǒng)架構(gòu)

2022-03-21 17:30:04

JetpackGoogle開發(fā)者

2020-10-09 07:56:52

Linux

2020-12-19 16:12:58

操作系統(tǒng)計算機科學

2023-09-11 06:32:30

VPAHPA容量

2023-11-20 08:18:49

Netty服務(wù)器

2023-05-15 08:44:15

Redis數(shù)據(jù)庫

2021-04-28 08:05:30

SpringCloudEureka服務(wù)注冊

2022-10-21 17:24:34

契約測試定位

2021-11-20 10:27:43

Python數(shù)據(jù)類型

2021-11-22 06:21:31

Python數(shù)據(jù)類型Python基礎(chǔ)

2021-05-29 10:11:00

Kafa數(shù)據(jù)業(yè)務(wù)

2023-07-31 08:18:50

Docker參數(shù)容器

2023-11-06 08:16:19

APM系統(tǒng)運維
點贊
收藏

51CTO技術(shù)棧公眾號