6000+字講透ElasticSearch 索引設計

来源:https://www.cnblogs.com/jiagooushi/archive/2023/05/11/17390832.html
-Advertisement-
Play Games

ElasticSearch 索引設計 在MySQL中資料庫設計非常重要,同樣在ES中資料庫設計也是非常重要的 概述 我們創建索引就像創建表結構一樣,必須非常慎重的,索引如果創建不好後面會出現各種各樣的問題 索引設計的重要性 索引創建後,索引的分片只能通過_split和_shrink介面對其進行成倍的 ...


ElasticSearch 索引設計

img

在MySQL中資料庫設計非常重要,同樣在ES中資料庫設計也是非常重要的

概述

我們創建索引就像創建表結構一樣,必須非常慎重的,索引如果創建不好後面會出現各種各樣的問題

索引設計的重要性

索引創建後,索引的分片只能通過_split_shrink介面對其進行成倍的增加和縮減

主要是因為es的數據是通過_routing分配到各個分片上面的,所以本質上是不推薦去改變索引的分片數量的,因為這樣都會對數據進行重新的移動。

還有就是索引只能新增欄位,不能對欄位進行修改和刪除,缺乏靈活性,所以每次都只能通過_reindex重建索引了,還有就是一個分片的大小以及所以分片數量的多少嚴重影響到了索引的查詢和寫入性能,所以可想而知,設計一個好的索引能夠減少後期的運維管理和提高不少性能,所以前期對索引的設計是相當的重要的。

基於時間的Index設計

Index設計時要考慮的第一件事,就是基於時間對Index進行分割,即每隔一段時間產生一個新的Index

這樣設計的目的

因為現實世界的數據是隨著時間的變化而不斷產生的,切分管理可以獲得足夠的靈活性和更好的性能

img

如果數據都存儲在一個Index中,很難進行擴展和調整,因為Elasticsearch中Index的某些設置在創建時就設定好了,是不能更改的,比如Primary Shard的個數。

而根據時間來切分Index,則可以實現一定的靈活性,既可以在數據量過大時及時調整Shard個數,也可以及時響應新的業務需求。

大多數業務場景下,客戶對數據的請求都會命中在最近一段時間上,通過切分Index,可以儘可能的避免掃描不必要的數據,提高性能。

時間間隔

根據上面的分析,自然是時間越短越能保持靈活性,但是這樣做就會導致產生大量的Index,而每個Index都會消耗資源來維護其元信息的,因此需要在靈活性、資源和性能上做權衡

  • 常見的間隔有小時、天、周和月:先考慮總共要存儲多久的數據,然後選一個既不會產生大量Index又能夠滿足一定靈活性的間隔,比如你需要存儲6個月的數據,那麼一開始選擇“周”這個間隔就會比較合適。
  • 考慮業務增長速度:假如業務增長的特別快,比如上周產生了1億數據,這周就增長到了10億,那麼就需要調低這個間隔來保證有足夠的彈性能應對變化。
如何實現分割

切分行為是由客戶端(數據的寫入端)發起的,根據時間間隔與數據產生時間將數據寫入不同的Index中,為了易於區分,會在Index的名字中加上對應的時間標識

創建新Index這件事,可以是客戶端主動發起一個創建的請求,帶上具體的Settings、Mappings等信息,但是可能會有一個時間錯位,即有新數據寫入時新的Index還沒有建好,Elasticsearch提供了更優雅的方式來實現這個動作,即Index Template

分片設計

所謂分片設計,就是如何設定主分片的個數

看上去只是一個數字而已,也許在很多場景下,即使不設定也不會有問題(ES7預設是1個主分片一個副本分片),但是如果不提前考慮,一旦出問題就可能導致系統性能下降、不可訪問、甚至無法恢復,換句話說,即使使用預設值,也應該是通過足夠的評估後作出的決定,而非拍腦袋定的。

限制分片大小

單個Shard的存儲大小不超過30GB

Elastic專家根據經驗總結出來大家普遍認為30GB是個合適的上限值,實踐中發現單個Shard過大(超過30GB)會導致系統不穩定。

其次,為什麼不能超過30GB?主要是考慮Shard Relocate過程的負載,我們知道,如果Shard不均衡或者部分節點故障,Elasticsearch會做Shard Relocate,在這個過程中會搬移Shard,如果單個Shard過大,會導致CPU、IO負載過高進而影響系統性能與穩定性。

評估分片數量

單個Index的Primary Shard個數 = k * 數據節點個數

在保證第一點的前提下,單個Index的Primary Shard個數不宜過多,否則相關的元信息與緩存會消耗過多的系統資源,這裡的k,為一個較小的整數值,建議取值為1,2等,整數倍的關係可以讓Shard更好地均勻分佈,可以充分的將請求分散到不同節點上。

小索引設計

對於很小的Index,可以只分配1~2個Primary Shard的

有些情況下,Index很小,也許只有幾十、幾百MB左右,那麼就不用按照第二點來分配了,只分配1~2個Primary Shard是可以,不用糾結。

使用索引模板

就是把已經創建好的某個索引的參數設置(settings)和索引映射(mapping)保存下來作為模板,在創建新索引時,指定要使用的模板名,就可以直接重用已經定義好的模板中的設置和映射

Elasticsearch基於與索引名稱匹配的通配符模式將模板應用於新索引,也就是說通過索引進行匹配,看看新建的索引是否符合索引模板,如果符合,就將索引模板的相關設置應用到新的索引,如果同時符合多個索引模板呢,這裡需要對參數priority進行比較,這樣會選擇priority大的那個模板進行創建索引。

在創建索引模板時,如果匹配有包含的關係,或者相同,則必須設置priority為不同的值,否則會報錯,索引模板也是只有在新創建的時候起到作用,修改索引模板對現有的索引沒有影響,同樣如果在索引中設置了一些設置或者mapping都會覆蓋索引模板中相同的設置或者mapping

索引模板的用途

索引模板一般用在時間序列相關的索引中。

也就是說, 如果你需要每間隔一定的時間就建立一次索引,你只需要配置好索引模板,以後就可以直接使用這個模板中的設置,不用每次都設置settings和mappings.

創建索引模板
COPYPUT _index_template/logstash-village
{
  "index_patterns": [
    "logstash-village-*"  // 可以通過"logstash-village-*"來適配創建的索引
  ],
  "template": {
    "settings": {
      "number_of_shards": "3", //指定模板分片數量
      "number_of_replicas": "2"  //指定模板副本數量
    },
    "aliases": {
      "logstash-village": {}  //指定模板索引別名
    },
    "mappings": {   //設置映射
      "dynamic": "strict", //禁用動態映射
      "properties": {
        "@timestamp": {
          "type": "date",
           "format": "strict_date_optional_time||epoch_millis||yyyy-MM-dd HH:mm:ss"
        },
        "@version": {
          "doc_values": false,
          "index": "false",
          "type": "integer"
        },
        "name": {
          "type": "keyword"
        },
        "province": {
          "type": "keyword"
        },
        "city": {
          "type": "keyword"
        },
        "area": {
          "type": "keyword"
        },
        "addr": {
          "type": "text",
          "analyzer": "ik_smart"
        },
        "location": {
          "type": "geo_point"
        },
        "property_type": {
          "type": "keyword"
        },
        "property_company": {
          "type": "text",
          "analyzer": "ik_smart"
        },
        "property_cost": {
          "type": "float"
        },
        "floorage": {
          "type": "float"
        },
        "houses": {
          "type": "integer"
        },
        "built_year": {
          "type": "integer"
        },
        "parkings": {
          "type": "integer"
        },
        "volume": {
          "type": "float"
        },
        "greening": {
          "type": "float"
        },
        "producer": {
          "type": "keyword"
        },
        "school": {
          "type": "keyword"
        },
        "info": {
          "type": "text",
          "analyzer": "ik_smart"
        }
      }
    }
  }
}
模板參數

下麵是創建索引模板的一些參數

參數名稱 參數介紹
index_patterns 必須配置,用於在創建期間匹配索引名稱的通配符(*)表達式數組
template 可選配置,可以選擇包括別名、映射或設置配置
composed_of 可選配置,組件模板名稱的有序列表。組件模板按指定的順序合併,這意味著最後指定的組件模板具有最高的優先順序
priority 可選配置,創建新索引時確定索引模板優先順序的優先順序。選擇具有最高優先順序的索引模板。如果未指定優先順序,則將模板視為優先順序為0(最低優先順序)
version 可選配置,用於外部管理索引模板的版本號
_meta 可選配置,關於索引模板的可選用戶元數據,可能有任何內容

映射配置

上面我們配置了映射模板,但是我們用到了映射,下麵我們說下映射

什麼是映射

在創建索引時,可以預先定義欄位的類型(映射類型)及相關屬性

資料庫建表的時候,我們DDL依據一般都會指定每個欄位的存儲類型,例如:varchar、int、datetime等,目的很明確,就是更精確的存儲數據,防止數據類型格式混亂,在Elasticsearch中也是這樣,創建索引的時候一般也需要指定索引的欄位類型,這種方式稱為映射(Mapping)

被動創建(動態映射)

此時欄位和映射類型不需要事先定義,只需要存在文檔的索引,當向此索引添加數據的時候當遇到不存在的映射欄位,ES會根據數據內容自動添加映射欄位定義。

動態映射規則

使用動態映射的時候,根據傳遞請求數據的不同會創建對應的數據類型

數據類型 Elasticsearch 數據類型
null 不添加任何欄位
true或者false boolean類型
浮點數據 float類型
integer數據 long類型
object object類型
array 取決於數組中的第一個非空值的類型。
string 如果此內容通過了日期格式檢測,則會被認為是date數據類型 如果此值通過了數值類型檢測則被認為是double或者long數據類型 帶有關鍵字子欄位會被認為一個text欄位
禁止動態映射

一般生產環境下需要禁用動態映射,使用動態映射可能出現以下問題

  1. 造成集群元數據一直變更,導致不穩定;
  2. 可能造成數據類型與實際類型不一致;

如何禁用動態映射,動態mappingdynamic欄位進行配置,可選值及含義如下

  • true:支持動態擴展,新增數據有新的欄位屬性時,自動添加對於的mapping,數據寫入成功
  • false:不支持動態擴展,新增數據有新的欄位屬性時,直接忽略,數據寫入成功
  • strict:不支持動態擴展,新增數據有新的欄位時,報錯,數據寫入失敗

主動創建(顯示映射)

動態映射只能保證最基礎的數據結構的映射

所以很多時候我們需要對欄位除了數據結構定義更多的限制的時候,動態映射創建的內容很可能不符合我們的需求,所以可以使用PUT {index}/mapping來更新指定索引的映射內容。

映射類型

我們要創建映射必須還要知道映射類型,否則就會走預設的映射類型,下麵我們看看常用的映射類型

準備工作

我們先創建一個用於測試映射類型的索引

COPYPUT mapping_demo

字元串類型

字元串類型是我們最常用的類型之一,我們操作的時候字元串類型可以被設置為以下幾種類型

text

當一個欄位是要被全文搜索的,比如Email內容、產品描述,應該使用text類型,text類型會被分詞

設置text類型以後,欄位內容會被分詞,在生成倒排索引以前,字元串會被分析器分成一個一個詞項,text類型的欄位不用於排序,很少用於聚合

keyword

keyword類型不會被分詞,常用於關鍵字搜索,比如姓名、email地址、主機名、狀態碼和標簽等

如果欄位需要進行過濾(比如查姓名是張三發佈的博客)、排序、聚合,keyword類型的欄位只能通過精確值搜索到,常常被用來過濾、排序和聚合

兩者區別

它們的區別在於text會對欄位進行分詞處理而keyword則不會進行分詞

也就是說如果欄位是text類型,存入的數據會先進行分詞,然後將分完詞的片語存入索引,而keyword則不會進行分詞,直接存儲,這樣劃分數據更加節省記憶體。

使用案例

我們先創建一個映射,name是keyword類型,描述是text類型的

COPYPUT mapping_demo/_mapping
{
  "properties": {
    "name": {
        "type": "keyword"
     },
      "city": {
        "type": "text",
        "analyzer": "ik_smart"
     }
  }
}

插入數據

COPYPUT mapping_demo/_doc/1
{
  "name":"北京小區",
  "city":"北京市昌平區回龍觀街道"
}

對於keyword的name欄位進行精確查詢

COPYGET mapping_demo/_search
{
  "query": {
    "term": {
      "name": "北京小區"
    }
  }
}

對於text的city進行模糊查詢

COPYGET mapping_demo/_search
{
  "query": {
    "term": {
      "city": "北京市"
    }
  }
}

數字類型

數字類型也是我們最常用的類型之一,下麵我們看下數字類型的使用

類型 取值範圍
long -263 ~ 263
integer -231 ~ 231
short -215 ~ 215
byte -27 ~ 27
double 64位的雙精度 IEEE754 浮點類型
float 32位的雙精度 IEEE754 浮點類型
half_float 16位的雙精度 IEEE754 浮點類型
scaled_float 縮放類型的浮點類型
註意事項
  • 在滿足需求的情況下,優先使用範圍小的欄位,欄位長度越小,索引和搜索的效率越高。

日期類型

JSON表示日期

JSON沒有表達日期的數據類型,所以在ES裡面日期只能是下麵其中之一

  • 格式化的日期字元串,比如:"2015-01-01" or "2015/01/01 12:10:30"
  • 用數字表示的從新紀元開始的毫秒數
  • 用數字表示的從新紀元開始的秒數(epoch_second)

註意點:毫秒數的值是不能為負數的,如果時間在1970年以前,需要使用格式化的日期表達

ES如何處理日期

在ES的內部,時間會被轉換為UTC時間(如果聲明瞭時區)並使用從新紀元開始的毫秒數的長整形數字類型的進行存儲,在日期欄位上的查詢,內部將會轉換為使用長整形的毫秒進行範圍查詢,根據與欄位關聯的日期格式,聚合和存儲欄位的結果將轉換回字元串

註意點:日期最終都會作為字元串呈現,即使最開始初始化的時候是利用JSON文檔的long聲明的

預設日期格式

日期的格式可以被定製化的,如果沒有聲明日期的格式,它將會使用預設的格式:

COPY"strict_date_optional_time||epoch_millis"

這意味著它將會接收帶時間戳的日期,它將遵守strict_date_optional_time限定的格式(yyyy-MM-dd'T'HH:mm:ss.SSSZ 或者 yyyy-MM-dd)或者毫秒數

日期格式示例
COPYPUT mapping_demo/_mapping
{
  "properties": {
    "datetime": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
     }
  }
}
# 添加數據
PUT mapping_demo/_doc/2
{
  "name":"河北區",
  "city":"河北省小區",
  "datetime":"2022-02-21 11:35:42"
}
日期類型參數

下麵表格裡的參數可以用在date欄位上面

參數 說明
doc_values 該欄位是否按照列式存儲在磁碟上以便於後續進行排序、聚合和腳本操作,可配置 true(預設)或 false
format 日期的格式
locale 解析日期中時使用了本地語言表示月份時的名稱和/或縮寫,預設是 ROOT locale
ignore_malformed 如果設置為true,則奇怪的數字就會被忽略,如果是false(預設)奇怪的數字就會導致異常並且該文檔將會被拒絕寫入。需要註意的是,如果在腳本參數中使用則該屬性不能被設置
index 該欄位是否能快速的被查詢,預設是true。date類型的欄位只有在doc_values設置為true時才能被查詢,儘管很慢。
null_value 替代null的值,預設是null
on_script_error 定義在腳本中如何處理拋出的異常,fail(預設)則整個文檔會被拒絕索引,continue:繼續索引
script 如果該欄位被設置,則欄位的值將會使用該腳本產生,而不是直接從source裡面讀取。
store true or false(預設)是否在 _source 之外在獨立存儲一份

布爾類型

boolean類型用於存儲文檔中的true/false

範圍類型

顧名思義,範圍類型欄位中存儲的內容就是一段範圍,例如年齡30-55歲,日期在2020-12-28到2021-01-01之間等

類型範圍

es中有六種範圍類型:

  • integer_range
  • float_range
  • long_range
  • double_range
  • date_range
  • ip_range
使用實例
COPYPUT mapping_demo/_mapping
{
  "properties": {
    "age_range": {
        "type": "integer_range"
     }
  }
}

# 指定年齡範圍,可以使用 gt、gte、lt、lte。
PUT mapping_demo/_doc/3
{
  "name":"張三",
  "age_range":{
    "gt":20,
    "lt":30
  }
}

分詞器

什麼是分詞器

分詞器的主要作用將用戶輸入的一段文本,按照一定邏輯,分析成多個詞語的一種工具

顧名思義,文本分析就是把全文本轉換成一系列單詞(term/token)的過程,也叫分詞,在 ES 中,Analysis 是通過分詞器(Analyzer) 來實現的,可使用 ES 內置的分析器或者按需定製化分析器。

舉一個分詞簡單的例子:比如你輸入 Mastering Elasticsearch,會自動幫你分成兩個單詞,一個是 mastering,另一個是 elasticsearch,可以看出單詞也被轉化成了小寫的。

圖片

分詞器構成

分詞器是專門處理分詞的組件,分詞器由以下三部分組成:

character filter

接收原字元流,通過添加、刪除或者替換操作改變原字元流

例如:去除文本中的html標簽,或者將羅馬數字轉換成阿拉伯數字等,一個字元過濾器可以有零個或者多個

tokenizer

簡單的說就是將一整段文本拆分成一個個的詞

例如拆分英文,通過空格能將句子拆分成一個個的詞,但是對於中文來說,無法使用這種方式來實現,在一個分詞器中,有且只有一個tokenizeer

token filters

將切分的單詞添加、刪除或者改變

例如將所有英文單詞小寫,或者將英文中的停詞a刪除等,在token filters中,不允許將token(分出的詞)position或者offset改變,同時,在一個分詞器中,可以有零個或者多個token filters

分詞順序

圖片

同時 Analyzer 三個部分也是有順序的,從圖中可以看出,從上到下依次經過 Character FiltersTokenizer 以及 Token Filters,這個順序比較好理解,一個文本進來肯定要先對文本數據進行處理,再去分詞,最後對分詞的結果進行過濾。

測試分詞

可以通過_analyzerAPI來測試分詞的效果,我們使用下麵的html過濾分詞

COPYPOST _analyze
{
    "text":"<b>hello world<b>"  # 輸入的文本
    "char_filter":["html_strip"], # 過濾html標簽
	"tokenizer":"keyword", #原樣輸出
}

image-20220808135231869

什麼時候分詞

文本分詞會發生在兩個地方:

  • 創建索引:當索引文檔字元類型為text時,在建立索引時將會對該欄位進行分詞。
  • 搜索:當對一個text類型的欄位進行全文檢索時,會對用戶輸入的文本進行分詞。

創建索引時指定分詞器

如果設置手動設置了分詞器,ES將按照下麵順序來確定使用哪個分詞器

  • 先判斷欄位是否有設置分詞器,如果有,則使用欄位屬性上的分詞器設置
  • 如果設置了analysis.analyzer.default,則使用該設置的分詞器
  • 如果上面兩個都未設置,則使用預設的standard分詞器
欄位指定分詞器

為addr屬性指定分詞器,這裡我們使用的是中文分詞器

COPYPUT my_index
{
  "mappings": {
    "properties": {
     "info": {
        "type": "text",
        "analyzer": "ik_smart"
       }
    }
  }
}
設置預設分詞器
COPYPUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "default":{
          "type":"simple"
        }
      }
    }
  }
}

搜索時指定分詞器

在搜索時,通過下麵參數依次檢查搜索時使用的分詞器,這樣我們的搜索語句就會先分詞,然後再來進行搜索

  • 搜索時指定analyzer參數
  • 創建mapping時指定欄位的search_analyzer屬性
  • 創建索引時指定settinganalysis.analyzer.default_search
  • 查看創建索引時欄位指定的analyzer屬性
  • 如果上面幾種都未設置,則使用預設的standard分詞器。
指定analyzer

搜索時指定analyzer查詢參數

COPYGET my_index/_search
{
  "query": {
    "match": {
      "message": {
        "query": "Quick foxes",
        "analyzer": "stop"
      }
    }
  }
}
指定欄位analyzer
COPYPUT my_index
{
  "mappings": {
    "properties": {
      "title":{
        "type":"text",
        "analyzer": "whitespace",
        "search_analyzer": "simple"
      }
    }
  }
}
指定預設default_seach
COPYPUT my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "default":{
          "type":"simple"
        },
        "default_seach":{
          "type":"whitespace"
        }
      }
    }
  }
}

內置分詞器

es在索引文檔時,會通過各種類型 Analyzer 對text類型欄位做分析

不同的 Analyzer 會有不同的分詞結果,內置的分詞器有以下幾種,基本上內置的 Analyzer 包括 Language Analyzers 在內,對中文的分詞都不夠友好,中文分詞需要安裝其它 Analyzer

分析器 描述 分詞對象 結果
standard 標準分析器是預設的分析器,如果沒有指定,則使用該分析器。它提供了基於文法的標記化(基於 Unicode 文本分割演算法,如 Unicode 標準附件 # 29所規定) ,並且對大多數語言都有效。 The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. [ the, 2, quick, brown, foxes, jumped, over, the, lazy, dog’s, bone ]
simple 簡單分析器將文本分解為任何非字母字元的標記,如數字、空格、連字元和撇號、放棄非字母字元,並將大寫字母更改為小寫字母。 The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. [ the, quick, brown, foxes, jumped, over, the, lazy, dog, s, bone ]
whitespace 空格分析器在遇到空白字元時將文本分解為術語 The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. [ The, 2, QUICK, Brown-Foxes, jumped, over, the, lazy, dog’s, bone. ]
stop 停止分析器與簡單分析器相同,但增加了刪除停止字的支持。預設使用的是 _english_ 停止詞。 The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. [ quick, brown, foxes, jumped, over, lazy, dog, s, bone ]
keyword 不分詞,把整個欄位當做一個整體返回 The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. [The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone.]
pattern 模式分析器使用正則表達式將文本拆分為術語。正則表達式應該匹配令牌分隔符,而不是令牌本身。正則表達式預設為 w+ (或所有非單詞字元)。 The 2 QUICK Brown-Foxes jumped over the lazy dog’s bone. [ the, 2, quick, brown, foxes, jumped, over, the, lazy, dog, s, bone ]
多種西語系 arabic, armenian, basque, bengali, brazilian, bulgarian, catalan, cjk, czech, danish, dutch, english等等 一組旨在分析特定語言文本的分析程式。

IK中文分詞器

IKAnalyzer

IKAnalyzer是一個開源的,基於java的語言開發的輕量級的中文分詞工具包

從2006年12月推出1.0版開始,IKAnalyzer已經推出了3個大版本,在 2012 版本中,IK 實現了簡單的分詞歧義排除演算法,標志著 IK 分詞器從單純的詞典分詞向模擬語義分詞衍化

中文分詞器演算法

中文分詞器最簡單的是ik分詞器,還有jieba分詞,哈工大分詞器等

分詞器 描述 分詞對象 結果
ik_smart ik分詞器中的簡單分詞器,支持自定義字典,遠程字典 學如逆水行舟,不進則退 [學如逆水行舟,不進則退]
ik_max_word ik_分詞器的全量分詞器,支持自定義字典,遠程字典 學如逆水行舟,不進則退 [學如逆水行舟,學如逆水,逆水行舟,逆水,行舟,不進則退,不進,則,退]

ik_smart

原始內容
COPY傳智教育的教學質量是杠杠的
測試分詞
COPYGET _analyze
{
  "analyzer": "ik_smart",
  "text": "傳智教育的教學質量是杠杠的"
}

image-20220808115450647

ik_max_word

原始內容
COPY傳智教育的教學質量是杠杠的
測試分詞
COPYGET _analyze
{
  "analyzer": "ik_max_word",
  "text": "傳智教育的教學質量是杠杠的"
}

image-20220808115513668

本文由傳智教育博學谷狂野架構師教研團隊發佈。

如果本文對您有幫助,歡迎關註點贊;如果您有任何建議也可留言評論私信,您的支持是我堅持創作的動力。

轉載請註明出處!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ​ 去年年底的因為業務需要需要在使用tk.mybaits框架的系統中實現指定欄位的更新,可是tk.mybaits框架本身並不支持這個功能,我翻遍了CSDN和其他相關的技術相關的網站都沒有找到相關的解決方法。於是我通過幾天的翻閱相關資料和摸索後終於實現了這個功能。最近事情不是很多,想到又想到了去年解決 ...
  • 原文地址: JavaFx實現倒計時按鈕組件(類似發送激活碼) - Stars-One的雜貨小窩 本文基於TornadoFx框架進行編寫,封裝工具代碼是kotlin版本 然後也是順便把這個封裝成了stars-one/common-controls 里的xCountDownBtn 效果 思路 點擊按鈕的 ...
  • Spring是什麼? Spring是一個輕量級的控制反轉(IoC)和麵向切麵(AOP)的容器框架。 Spring的優點 通過控制反轉和依賴註入實現松耦合。 支持面向切麵的編程,並且把應用業務邏輯和系統服務分開。 通過切麵和模板減少樣板式代碼。 聲明式事務的支持。可以從單調繁冗的事務管理代碼中解脫出來 ...
  • Docker 是一個開源的應用容器引擎,可以讓開發者將應用程式打包成一個容器,並通過容器來部署、運行和管理應用程式。Docker 的核心概念包括容器和鏡像。容器是鏡像的可運行實例,可以通過 Docker API 或 CLI 來創建、啟動、停止、移動或刪除容器。鏡像是一個只讀模板,包含了創建 Dock... ...
  • 1.引言 高併發場景在現場的日常工作中很常見,特別是在互聯網公司中,這篇文章就來通過秒殺商品來模擬高併發的場景。文章末尾會附上文章的所有代碼、腳本和測試用例。 本文環境: SpringBoot 2.5.7 + MySQL 8.0 X + MybatisPlus + Swagger2.9.2 模擬工具 ...
  • JScrollPane 組件() 功能介紹: 當容器的顯示區域不足以同時顯示所有組件的時候,滾動面版JScrollPane(後省略為JS)可以通過滾動的方式將組件的內容展示出來。 使用方法: JS通過將一些組件先添加到JPanel中,再將JPanel添加到JS上,而JTextArea、JList、J ...
  • #用Python實現藝術繪畫 藝術繪畫是一個創造性的過程,包括繪畫、素描和繪畫。藉助Python編程語言,您可以模擬藝術繪畫的過程。該過程包括以下步驟: 1.導入所需的庫-您需要導入NumPy、OpenCV和Matplotlib等庫來執行圖像處理任務。 2.載入圖像-您可以使用OpenCV載入圖像。 ...
  • Neo4j是一個高性能的開源的,使用Java語言實現的NoSQL圖資料庫,它將結構化數據存儲在網路上而不是表中。它是一個嵌入式的、基於磁碟的、具備完全的事務特性的Java持久化引擎,但是它將結構化數據存儲在網路(從數學角度叫做圖)上而不是表中。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...