成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

一文帶你掌握Elasticsearch復合字段類型:Array、Flattened、Nested在業務系統中最佳實踐

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

1.概述

elasticsearch在當下互聯網系統中使用非常廣泛,是一個非常熱門的組件框架。那elasticsearch到底是什么呢?

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

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

2.映射mapping

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

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

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

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

數據驗證:映射可以確保寫入的文檔符合預期的數據結構和類型。

映射mapping分為:動態映射和靜態映射

2.1 動態映射

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

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

PUT user_info

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

緊接著我們直接插入一條es文檔數據

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

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

GET user_info/_mapping

查詢結果如下:

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

可以看到,es在我們插入文檔數據時自動檢測字段類型動態定義了mapping結構。

2.2 靜態映射

靜態映射就和關系型數據庫表結構加字段一樣,在插入es文檔數據之前,先定義字段mapping再插入數據,比如我們往user_info添加一個身份證號idCard:

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

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

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

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

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

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

keyword 類型的字段不會被分詞,適合存儲如ID、狀態、標簽等字符串數據。

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

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

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

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

3.使用數組Array實現一對多查詢

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

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

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

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]
    }
  }
}

查詢結果id=10,11,12都命中了。

Java查詢實現代碼:

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

關于Spring Boot整合restHighLevelClient實現es相關操作,請查看上面的入門篇

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

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

只命中id=11這一條數據

Java實現代碼:

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

數組Array的限制:無法建立數組元素之間的關系

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

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

解決方案:如果你需要這種關聯關系,應使用 nested 類型來代替數組字段。后面會講。

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

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

4.使用Flattened存儲動態字段

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

該類型會將嵌套 JSON 對象的鍵值扁平化為單一層級字段。開搞!!!先定一個字段存儲用戶附加信息:

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

插入數據,我們在上面的數據更新字段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的信息都不太一樣,主打就是一個動態字段信息。接下來查詢看看:

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

查詢結果會命中id=10這條數據

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

5.使用Nested存儲對象數組

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

nested 類型允許 Elasticsearch 以“獨立文檔”方式存儲每個嵌套對象,并維持每個對象內字段之間的關系。這樣可以確保查詢到的數據和文檔結構一致,避免出現跨對象匹配的情況。

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

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

寫入數據,基于上面的數據寫入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的數據:

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

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

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

nested 類型適合嵌套對象數組的結構化數據,支持精確的對象內匹配查詢和聚合。當嵌套對象只需要簡單查詢、沒有嚴格的對象內關聯需求時,使用 Flattened 類型更高效。

6.總結

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

字段類型

適用場景

優點

缺點

Array

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

易用、性能好

無法維護元素之間的關系

Flattened

動態鍵值對結構(如可變的配置、元數據)

占用存儲空間少、動態字段支持好

不支持嵌套關系查詢

Nested

多層級結構對象,且需要查詢對象內部關系

支持復雜的關系查詢

性能和存儲開銷大

簡單來說:

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

根據你的業務需求,合理選擇字段類型可以顯著提升系統的查詢性能和數據管理效率。

責任編輯:武曉燕 來源: Shepherd進階筆記
相關推薦

2023-12-21 17:11:21

Containerd管理工具命令行

2022-12-20 07:39:46

2023-12-15 09:45:21

阻塞接口

2020-12-18 11:54:22

Linux系統架構

2021-02-22 09:05:59

Linux字符設備架構

2021-06-04 09:35:05

Linux字符設備架構

2022-02-18 10:13:07

SolrElasticSea開源

2022-03-21 17:30:04

JetpackGoogle開發者

2020-10-09 07:56:52

Linux

2020-12-19 16:12:58

操作系統計算機科學

2025-07-02 08:54:01

2022-10-21 17:24:34

契約測試定位

2023-11-20 08:18:49

Netty服務器

2023-07-31 08:18:50

Docker參數容器

2021-05-29 10:11:00

Kafa數據業務

2022-11-11 19:09:13

架構

2023-11-06 08:16:19

APM系統運維

2021-04-28 08:05:30

SpringCloudEureka服務注冊

2023-09-11 06:32:30

VPAHPA容量

2023-05-15 08:44:15

Redis數據庫
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 色综合久久久 | 国产高清久久 | 7777在线视频 | 美女二区 | 日韩一区二区三区视频 | 国产精品福利在线 | 色www精品视频在线观看 | 久久久久久久久久久久亚洲 | 九九天堂网 | 久久久久久精 | 日韩免费视频 | 精品一区国产 | 免费一二区 | 久久国产日本 | 视频精品一区二区三区 | 国产91丝袜在线熟 | 国产一区精品 | 国产精品美女久久久久久久久久久 | 精产国产伦理一二三区 | 黄色亚洲| 欧美极品视频在线观看 | 亚洲一区二区三区高清 | 免费观看的黄色网址 | 国产精品美女久久久免费 | 夜夜草 | 欧美中文字幕一区二区三区亚洲 | 日韩视频精品在线 | 欧美黄在线观看 | 欧美成视频 | 欧美综合国产精品久久丁香 | 成人国产精品色哟哟 | 亚洲视频在线观看 | 颜色网站在线观看 | 99热精品6 | 99久久婷婷国产综合精品电影 | 亚洲国产精选 | 中文字幕成人免费视频 | 亚洲精品不卡 | av黄色免费在线观看 | 男女羞羞视频在线看 | 一区二区视频在线 |