hirp,中文譯名啁啾(讀音:“周糾”),是一種編碼脈沖技術。CSS是英文Chirp Spread Spectrum的縮寫,中文意為啁啾擴頻,又稱線性調頻擴頻,是數字通信中的一種擴頻技術。CSS技術能夠提升無線通信的性能和距離,實現比FSK(Frequency Shift Keying,頻移鍵控)等調制技術距離更遠的無線通信,這非常有助于非蜂窩廣域網絡規模化的組網應用。本文就從CSS技術、市場、射頻收發器等方面做簡要闡述。
CSS擴頻技術傳輸性能優異 實現更遠距離的無線通信
CSS技術并非是一種新的技術。在自然界里,Chirp脈沖就為海豚和蝙蝠等生物所用。20世紀40年代Hüttmann教授發明了雷達應用專利,后由Sidney Darlington進一步將CSS技術引入雷達系統創造性地開發了脈沖壓縮(Chirp)雷達。自1997年以來人們開始研究將CSS技術應用于商業的無線數據傳輸。后來,IEEE 802.15.4標準將CSS指定為了一種用于低速率無線個人局域網(LR-WPAN)的技術,實現了數據速率可擴展性、遠距離、更低功耗和成本,其與差分相移鍵控調制(DPSK)等技術相結合,可以實現更好的通信性能。CSS技術使用了其全部分配帶寬來廣播信號,從而使其對信道噪聲具有一定的魯棒性。CSS技術在非常低的功率下也能夠抵抗多徑衰落,非常適用于要求低功耗和較低數據速率的應用場景。CSS技術的低成本、低功耗、遠距離以及數據速率的可擴展性等特性為產品商業化應用提供了現實的可能。
時域線性擴頻調頻upchirp示例 來源:Wikipedia
從CSS技術應用情況來看,德國Nanotron公司使用CSS技術在2.4GHz頻段上實現了570米的距離通信。美國Semtech公司的LoRa產品使用CSS技術在Sub-1GHz頻段上實現了幾公里,甚至幾十公里的距離通信。
CSS技術通信距離遠可以在一定范圍內實現更大規模的無線連接,大大降低無線接入和組網的成本,組建經濟高效的無線廣域網絡,有助于物聯網絡規模化部署應用。CSS技術的普及應用將為新興的非蜂窩廣域網絡市場的發展注入了新的活力,將會有力地推動行業應用的發展。
非蜂窩廣域網絡方興未艾 物聯網發展步入規模化應用階段
低功耗廣域網絡(Low-Power Wide Area Network, LPWAN)大致可以分為蜂窩和非蜂窩廣域網絡。蜂窩廣域網絡是指由運營商建設的基于蜂窩技術的網絡,一般是指3GPP主導的物聯網標準,代表技術有NB-IoT、LTE-M(eMTC)和EC-GSM-IoT等;非蜂窩廣域網絡主要是指由企業自主建設使用免許可頻段組建的網絡,代表技術有SIGFOX、LoRaWAN、ZETA等。也有的提出0G網絡,是相對于1G/2G/3G/4G而言,在通信領域一般是指蜂窩移動電話之前的移動電話技術,如無線電話。在物聯網領域,0G指的是一個低帶寬的無線網絡,沒有SIM卡、沒有流量、低成本接入、遠距離通信、傳輸少量數據的網絡,也就是非蜂窩廣域網絡。非蜂窩廣域網絡的發展是源于對數據大規模采集和大量設備管理等的需求,并借助互聯網技術和平臺提升了基于數據的智能化管理水平。物聯網市場發展步入規模化應用階段。目前,非蜂窩廣域網絡主要應用于市政、園區、水務、消防、物流、家居、電力、社區、工廠、農業、環境等領域。
不同網絡技術示意圖
實際上,非蜂窩廣域網絡和蜂窩廣域網絡相互之間是一種相互依存互為補充的關系。一般地,非蜂窩廣域網絡都是通過網關(或稱為集中器,或稱為基站)連接到互聯網,而網關連接到互聯網的方式一般是有線或蜂窩網絡等公網,最終還是要走公網的管道,畢竟有線和蜂窩網絡是廣泛存在的基礎性網絡。另一方面,傳感器或設備多是基于微控制器(MCU)的,受其資源限制,僅可運行輕量的簡單通信協議或定制化通信協議,通過網關轉換成互聯網協議(IP),網關起到了非蜂窩廣域網絡和互聯網連接器的作用。非蜂窩廣域網絡更是蜂窩網絡的拓展延伸。非蜂窩廣域網絡不同的無線接入技術可以滿足物聯網實際部署中各種各樣無線連接的應用需求,為傳感器網絡或設備聯網提供了靈活的無線接入方式和便捷的網絡部署。
非蜂窩和蜂窩技術也可以相互融合。最近有報道稱,在手機上集成了無線通信技術,可以在沒有蜂窩網絡的情況下,實現兩機或多機的無線遠距離相互通信,并可以實現自組網、定位等功能,這也為非蜂窩廣域網絡的應用提供了新的應用場景。
同時,非蜂窩網絡也在國家電網方面具有非常強勁的發展勢頭。據最近流傳的國家電網《電力設備無線傳感器網絡節點組網協議》顯示,針對電力設備無線傳感器網絡的組網和傳感器接入應用,在物理層協議規范中有對CSS物理層進行了定義,”CSS物理層:工作在470-510MHz或者2400-2483.5MHz頻段,采用線性調頻擴頻(CSS)調制。線性調頻擴頻(CSS)調制應符合LoRaWAN? 1.1 Specification 和IEEE Std 802.15.4TM-2015物理層的規定”。隨著泛在電力物聯網的建設發展,非蜂窩廣域網絡在泛在電力物聯網中將會有著更為廣闊的應用場景。除電力市場之外,其他抄表類市場應用,如:水表、氣表、燃氣表等,也是非蜂窩廣域網絡重要的典型應用市場。
另外,在一些重要的應用領域里,考慮到數據和安全等方面的因素,需要非蜂窩網絡技術將設備接入到專網上,以保障私域網絡的數據隱私和安全性。非蜂窩無線技術以其獨特的優勢在物聯網絡應用中發揮著重要的作用。
非蜂窩廣域網絡可以組建無線傳感網絡,連接和管理一定范圍內大量傳感器或設備等,也可以成為一種網絡基礎設施,由專門公司來提供網絡服務,或者說是一種物聯網絡運營服務。在國外物聯網運營模式已開始發展,如Sigfox等。而國內情況還處于探索發展階段,目前主要還是以提供解決方案為主。
低功耗廣域網絡市場發展前景看好 非蜂窩廣域網絡預期規模增速明顯
根據IHS Markit預測,2017年全球LPWAN連接數量為8753.7萬個,預計到2023年可達171698.4萬個,2017-2023年復合增長率(CAGR)為64%。其中,除NB-IoT和LTE-M等蜂窩連接之外,非蜂窩廣域網絡連接數量2017年為8124.8萬個,2023年預計可達84443.6萬個,2017-2023年復合增長率(CAGR)為48%。到2023年非蜂窩廣域網絡連接規模占比約為50%,非蜂窩廣域網絡市場未來具有很大的發展潛力。
2017-2023年全球LPWAN連接數量 來源:IHS Markit 2019
射頻收發器受市場關注 Sub-1GHz頻段更受青睞
一個完整的應用非蜂窩技術的應用圖包括感知層、網絡層和應用層。其中感知層中的射頻收發器主要用于傳感器和網關之間的信息交互。
非蜂窩技術系統應用框圖
射頻收發器是非蜂窩技術組網應用的關鍵器件,隨著非蜂窩廣域網絡的發展,射頻收發器產品越來越受到市場關注。從業界目前非蜂窩廣域網絡技術應用情況來看, 采用的都是國外半導體公司的射頻收發器產品,這些廠商有Semtech、ST、Silicon Labs、TI、NXP、ON等,鮮有國內半導體公司的產品。Semtech公司的LoRa產品在中國市場上得到了很多公司的支持,國內少數公司通過IP授權的方式獲得了LoRa IP,提供本地化產品,這些廠商有翱捷(ASR)、國民技術、華普等公司。隨著射頻收發器市場需求的發展,國內的一些芯片設計公司也開始研究和開發射頻收發器產品。最近有報道稱,國內上海磐啟微電子有限公司推出了基于CSS技術的Chirp-IOT芯片PAN3028,融合了多維信號調制技術解決了頻率不連續對射頻的影響,提高了接收靈敏度,在射頻收發器領域實現了新的技術突破。Chirp-IOT產品的國產化也填補了中國非蜂窩廣域網絡市場的空白。
由于射頻收發器在Sub-1GHz頻段上具有良好的無線傳輸特性,傳輸距離遠、障礙物穿透能力強等,非蜂窩廣域網絡基本都是采用Sub-1GHz射頻收發器組建網絡。下面是關于Sub-1GHz射頻收發器主要的廠商:
Sub-1GHz射頻收發器廠商
萬物智聯市場快速發展需求大 集成電路設計國產化迎新機遇
中國市場規模大,對集成電路的需求也大,而目前還較多地依賴于集成電路的進口。根據海關統計,2018年中國進口集成電路有4170億塊,進口金額達3107億美元。據國家統計局的統計顯示,我國2018年集成電路產量1739.47億個,國產集成電路產量不足進口量一半。近些年,國家不斷加大對集成電路產業的政策扶持力度,出現了一大批新的集成電路設計公司,集成電路技術水平也在逐步提升。加之近兩年中美貿易環境的變化,加速了集成電路國產化的速度。在涉及到國家核心重要應用領域,仍然是強調國產自主可控。這是中國集成電路設計公司一個重要的發展契機,也是非蜂窩廣域網絡行業一個發展機會。隨著萬物智聯市場的快速發展,中國集成電路設計也將會迎來一波新的發展機遇。
根據半導體行業協會的統計,2018年中國集成電路設計產值為2519.3億人民幣,同比增長21.5%,2009到2018年中國集成電路設計產值年復合增長率(CAGR)為28.7%,集成電路設計產業保持了較高的發展速度。
2009-2018年中國集成電路設計產值 來源:半導體行業協會
結語
CSS技術在無線通信方面具有顯著的優勢,有助于非蜂窩廣域網絡實現大范圍的組網應用。隨著物聯網市場無線連接需求的不斷增長,射頻收發器產品越來越受到芯片公司的關注。而國內射頻收發器產品廠商少,行業發展還比較薄弱,需要更多的國內射頻收發器廠商共同的參與,助力非蜂窩廣域網絡行業的發展,賦能非蜂窩廣域網無線超連接,創新更多的物聯網應用。
未來,隨著集成電路技術的不斷發展,或許會出現更多的新技術、新產品,這也將會大大豐富非蜂窩廣域網絡生態。“獨木不成林”。需要各行各業共同的參與,建立共建共享共榮的良性發展生態。
?
作簿是 Excel 文檔的基礎,基于工作簿的操作主要有新建、打開、保存工作簿,以及工作簿的保護與撤銷等。一個工作簿對象(Workbook)就是一個 Excel 文件,多個 Workbook 對象組成 Workbooks集合。工作簿對象包括工作表對象 Worksheet、單元格區域對象 Range、圖表對象 Chart 等。
[批量新建工作簿]
按照A列內容創建Excel文件
Sub 批量新建工作簿()
Dim str1 As String, wbPath As String
Dim i As Integer, n As Integer
Dim ws1 As Worksheet, wb1 As Workbook
Application.DisplayAlerts = False '禁止警告信息
Set ws1 = ActiveSheet '獲取當前工作表的引用
wbPath = ThisWorkbook.Path & "\例 1" '保存文件的目錄
n = ws1.Range("A1").End(xlDown).Row '總的數據行數
For i = 2 To n '循環創建工作簿
Set wb1 = Workbooks.Add '新建一個工作簿
wb1.SaveAs wbPath & "\" & ws1.Cells(i, 1) & ".xls" '保存工作簿
wb1.Close '關閉工作簿
Next
Application.DisplayAlerts = True
End Sub
打開工作簿
保存工作簿
更名保存工作簿
將工作簿保存為 Web 頁
Sub 將工作簿保存為 Web 頁()
ActiveWorkbook.SaveAs Filename:="MyWeb.htm", FileFormat:=xlHtml
End Sub
打開文本文件
使用 Workbooks 集合對象的 OpenText 方法,可載入一個文本文件,并將其作為包含單個工作表的新工作簿進行分列處理,然后在此工作表中放入經過分列處理的文本文件數據。該方法的語法格式如下:
表達式 .
OpenText(Filename, Origin, StartRow, DataType, TextQualifier, ConsecutiveDelimiter, Tab, Semicolon, Comma, Space, Other, OtherChar, FieldInfo, TextVisualLayout, DecimalSeparator, ThousandsSeparator, TrailingMinusNumbers, Local)
該方法的參數有很多,除了 Filename 為必需的參數之外,其他參數都可省略。各參數的含義如下。
● Filename:指定要打開和分列的文本文件的名稱。
● Origin:指定文本文件來源。可為常量 xlMacintosh、xlWindows 或 xlMSDOS。此外,它還可以是一個整數,表示所需代碼頁的代碼頁編號。例如,“1256”指定源文本文件的編碼是阿拉伯語。如果省略該參數,則此方法將使用“文本導入向導”中“文件原始格式”選項的當前設置。
● StartRow:文本分列處理的起始行號。默認值為 1。
● DataType:指定文件中數據的列格式。可為常量 xlDelimited 或 xlFixedWidth。如果未指定該參數,則 Excel 將嘗試在打開文件時確定列格式。
● TextQualifier:指定文本識別符號。
● ConsecutiveDelimiter:如果為 True,則將連續分隔符視為一個分隔符。默認值為False。
● Tab:如果為 True,則將制表符用作分隔符(DataType 必須為 xlDelimited)。默認值為 False。
● Semicolon:如果為 True,則將分號用作分隔符(DataType 必須為 xlDelimited)。默認值為 False。
● Comma:如果為 True,則將逗號用作分隔符(DataType 必須為 xlDelimited)。默認值為 False。
● Space:如果為 True,則將空格用作分隔符(DataType 必須為 xlDelimited)。默認值為 False。
● Other:如果為 True,則將 OtherChar 參數指定的字符用作分隔符(DataType 必須為 xlDelimited)。默認值為 False。
● OtherChar:(如果 Other 為 True,則為必選項)。當 Other 為 True 時,指定分隔符。如果指定了多個字符,則僅使用字符串中的第一個字符而忽略剩余字符。
● FieldInfo:包含單列數據相關分列信息的數組。對該參數的解釋取決于 DataType的值。如果此數據由分隔符分隔,則該參數為由兩個元素數組組成的數組,其中每個兩元素數組指定一個特定列的轉換選項。第一個元素為列標(從 1 開始),第二個元素是 XlColumnDataType 的常量之一,用于指定分列方式。
● TextVisualLayout:文本的可視布局。
● DecimalSeparator:識別數字時,Excel 使用的小數分隔符。默認設置為系統設置。
● ThousandsSeparator:識別數字時,Excel 使用的千位分隔符。默認設置為系統設置。
● TrailingMinusNumbers:如果應將結尾為減號字符的數字視為負數處理,則指定為True。如果為 False 或省略該參數,則將結尾為減號字符的數字視為文本處理。
● Local:如果分隔符、數字和數據格式應使用計算機的區域設置,則指定為 True。
Sub 打開文本文件()
Workbooks.OpenText Filename:="員工花名冊.txt", _
DataType:=xlDelimited, Tab:=True
End Sub
設置工作簿密碼
Sub 設置工作簿密碼()
Dim pw As String
pw = Application.InputBox(prompt:="請輸入保護工作簿的密碼:", _
Title:="輸入密碼", Type:=2)
ActiveWorkbook.Password = pw
ActiveWorkbook.Save
ActiveWorkbook.Close
End Sub
保護工作簿
Sub 保護工作簿()
Dim pw As String
pw = Application.InputBox(prompt:="請輸入保護工作簿的密碼:", _
Title:="輸入密碼", Type:=2)
ActiveWorkbook.Protect Password:=pw, Structure:=True, Windows:=True
End Sub
查看文檔屬性
判斷工作簿是否存在
判斷工作簿是否打開
Sub 判斷工作簿是否打開()
Dim str1 As String
str1 = Application.InputBox(prompt:="請輸入 Excel 工作簿文件名:", _
Title:="文件名", Type:=2)
If str1 = "False" Then Exit Sub
If Not WorkbookIsOpen(str1) Then
MsgBox "工作簿“" & str1 & "”未打開!"
Else
MsgBox "工作簿“" & str1 & "”已打開!"
End If
End Sub
以上程序調用了一個自定義函數 WorkbookIsOpen,該函數的 VBA 代碼如下:
Private Function WorkbookIsOpen(WorkBookName As String) As Boolean
'如果該工作簿已打開,則返回真
Dim wb As Workbook
On Error Resume Next
Set wb = Workbooks(WorkBookName)
If Err = 0 Then
WorkbookIsOpen = True
Else
WorkbookIsOpen = False
End If
End Function
備份工作簿
以上程序首先獲取對當前工作簿的引用,如果當前工作簿是新建工作簿,則彈出“另存為”對話框。接著獲取工作簿的全名,使用 InStrRev 函數查找工作簿的全名是否有擴展名,若有擴展名,則截取文件名的前面部分(不含擴展),再將文件名后面加上“.bak”,形成備份文件的名稱,最后保存當前工作簿,并使用備份文件名另存文件,得到備份文件。
限制工作簿使用時間
今日代碼文件
https://wws.lanzous.com/iZe8rnu5w9e
最近接到一個需求,將 MySQL 中的數據遷移到 Elasticsearch 中,并且相關的業務接口全部切換為使用 Elasticsearch 實現。
其中有個統計的功能,先根據 group 進行分組,然后對每個組內對象的 type 值進行分組統計。
舉個例子:對學生進行統計,相當于先按照班級分組,在統計每個班級里面男女生的人數。
我一想切換到 Elasticsearch 中,相當于嵌套子聚合,一個聚合查詢就出來結果,半小時搞定這個接口。
創建索引
PUT zuiyu_index
{
"settings": {
"number_of_replicas": 1,
"number_of_shards": 1
},
"mappings": {
"properties": {
"group": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"type": {
"type": "long"
}
}
}
}
插入測試數據
POST _bulk
{ "index" : { "_index" : "zuiyu_index", "_id" : "1" } }
{ "group" : "1","type":1 ,"sort":1}
{ "index" : { "_index" : "zuiyu_index", "_id" : "2" } }
{ "group" : "1","type":2 ,"sort":1}
{ "index" : { "_index" : "zuiyu_index", "_id" : "3" } }
{ "group" : "1","type":3 ,"sort":1}
{ "index" : { "_index" : "zuiyu_index", "_id" : "4" } }
{ "group" : "2","type":1 ,"sort":1}
{ "index" : { "_index" : "zuiyu_index", "_id" : "5" } }
{ "group" : "2","type":1 ,"sort":1}
{ "index" : { "_index" : "zuiyu_index", "_id" : "6" } }
{ "group" : "2","type":1 ,"sort":1}
{ "index" : { "_index" : "zuiyu_index", "_id" : "7" } }
{ "group" : "3","type":2 ,"sort":1}
{ "index" : { "_index" : "zuiyu_index", "_id" : "8" } }
{ "group" : "4","type":1 ,"sort":1}
{ "index" : { "_index" : "zuiyu_index", "_id" : "9" } }
{ "group" : "5","type":1 ,"sort":1}
{ "index" : { "_index" : "zuiyu_index", "_id" : "10" } }
{ "group" : "6","type":1 ,"sort":1}
{ "index" : { "_index" : "zuiyu_index", "_id" : "11" } }
{ "group" : "7","type":1 ,"sort":1}
{ "index" : { "_index" : "zuiyu_index", "_id" : "12" } }
{ "group" : "8","type":1 ,"sort":1}
{ "index" : { "_index" : "zuiyu_index", "_id" : "13" } }
{ "group" : "9","type":1 ,"sort":1}
{ "index" : { "_index" : "zuiyu_index", "_id" : "14" } }
{ "group" : "10","type":1 ,"sort":1}
{ "index" : { "_index" : "zuiyu_index", "_id" : "15" } }
{ "group" : "10","type":2 ,"sort":1}
{ "index" : { "_index" : "zuiyu_index", "_id" : "16" } }
{ "group" : "11","type":1 ,"sort":1}
{ "index" : { "_index" : "zuiyu_index", "_id" : "17" } }
{ "group" : "11","type":3 ,"sort":1}
像這種簡單的一條 sql 就出來結果的業務,我一般都是先寫個 sql 語句,然后根據 sql 再寫代碼。所以這里我就先寫了個DSL語句。
GET zuiyu_index/_search
{
"aggregations": {
"agg_group": {
"aggregations": {
"agg_type": {
"terms": {
"field": "type"
}
}
},
"terms": {
"field": "group.keyword"
}
}
},
"query": {
"bool": {
"must": [
{
"terms": {
"group.keyword": ["1","2","3","4","5","6","7","8","9","10","11"]
}
}
]
}
},
"size":0
}
同學們可以看一下上面的語句有問題嗎,如果你能發現問題,那么這篇文章也希望你能看下去,也許會有意想不到的收獲。
提示一下:就像標題所說,可以關心一下聚合桶的數量。
上述 DSL 語句執行之后,大眼一看 ,結果 OK,是我想要的,那就按這個邏輯直接寫 Java 代碼。上述 DSL 語句中聚合操作對應的 Java 代碼如下:
Aggregation aggType = Aggregation.of(agg -> agg.terms(t -> t.field("type")));
Aggregation aggGroup = Aggregation.of(agg -> agg.terms(t -> t.field("group"))
.aggregations("agg_type", aggType));
做接口數據層的遷移,最簡單的就是修改完業務代碼之后直接對比返回結果,保持返回結果的一致,這樣的修改對于前端來說沒有影響。
所以,修改完代碼之后直接拿接口的返回值與修改之前的版本進行比對,驗證業務邏輯是否一致。直接 F12 控制臺,找到該接口的返回值,復制,粘貼到對比工具中,進行對比。
此處使用的對比工具是 Beyond Compare 。
通過對比返回結果發現,聚合桶的數量少了一個。
上面的例子中,我們的預期結果是,最外層 group 的分組最少11個,排除 group 不存在的情況。這里 terms 中條件 group 在索引中都已存在。
然后我就趕緊再去執行了一遍上面 DSL 語句,一個一個的驗證聚合桶,發現返回結果中竟然沒有 group=9 的桶存在。
DSL 返回結果如下
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 17,
"relation": "eq"
},
"max_score": null,
"hits": []
},
"aggregations": {
"agg_group": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 1,
"buckets": [
{
"key": "1",
"doc_count": 3,
"agg_type": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 1,
"doc_count": 1
},
{
"key": 2,
"doc_count": 1
},
{
"key": 3,
"doc_count": 1
}
]
}
},
{
"key": "2",
"doc_count": 3,
"agg_type": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 1,
"doc_count": 3
}
]
}
},
{
"key": "10",
"doc_count": 2,
"agg_type": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 1,
"doc_count": 1
},
{
"key": 2,
"doc_count": 1
}
]
}
},
{
"key": "11",
"doc_count": 2,
"agg_type": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 1,
"doc_count": 1
},
{
"key": 3,
"doc_count": 1
}
]
}
},
{
"key": "3",
"doc_count": 1,
"agg_type": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 2,
"doc_count": 1
}
]
}
},
{
"key": "4",
"doc_count": 1,
"agg_type": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 1,
"doc_count": 1
}
]
}
},
{
"key": "5",
"doc_count": 1,
"agg_type": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 1,
"doc_count": 1
}
]
}
},
{
"key": "6",
"doc_count": 1,
"agg_type": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 1,
"doc_count": 1
}
]
}
},
{
"key": "7",
"doc_count": 1,
"agg_type": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 1,
"doc_count": 1
}
]
}
},
{
"key": "8",
"doc_count": 1,
"agg_type": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": 1,
"doc_count": 1
}
]
}
}
]
}
}
}
到了這,其實我還沒想到是什么原因造成的,然后看了好幾遍的聚合語句,都沒有發現問題。一度的自我懷疑,聚合不是這樣用的嗎,嵌套的聚合難道還有花樣?
官方文檔肯定是最權威的,所以去官方文檔看看吧,是不是可以給自己點靈感,找到解決方案。
首先去的是如下地址:
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html#run-sub-aggs
官方給的代碼示例好簡單,確實沒毛病,對我沒啥啟發,告辭轉下個網頁。
還是這個網頁,回到頁面頂端,有一個 Bucket 字樣的地方,點進去。
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket.html
在這個頁面,發現可以通過 search.max_buckets 設置請求返回聚合桶的總數,然后我腦海中那丟失的記憶回來了。
想起了在 Elasticsearch 聚合時,聚合桶的返回數量是可以指定的,但是怎么指定,參數是什么,我又忘了。
但是大方向肯定是這個了,我就開始找相關的資料,翻閱官網關于聚合的文檔,終于在官方文檔的嵌套聚合中找到了相關的說明。
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-composite-aggregation.html#_size
大體意思就是size參數可以控制返回聚合桶的數量,默認 10。
但是這里也沒有給出示例,我還是不會用啊。
畢竟咱也是有點 ES 基礎的,內心其實已經有了想法,大概知道怎么用了,只是還得需要確認下。
最后想起來之前寫過關于聚合的文章,抱著試試看的態度,在回顧一下吧。
聚合在Elasticsearch中的使用及示例驗證
發文日期,2023年8月2日,真是老了,才半年多的時間都忘了,好了回到主題。
在這篇文檔中,發現了 size 參數的使用,在這里終于確認,聚合桶數量需要指定,并且根據自己的查詢條件進行設置,或直接設置一個最大值兼容自己所有的聚合請求。
所以修改之后的 DSL 語句如下:
GET zuiyu_index/_search
{
"aggregations": {
"agg_group": {
"aggregations": {
"agg_type": {
"terms": {
"field": "type"
}
}
},
"terms": {
"field": "group.keyword",
"size": 11
}
}
},
"query": {
"bool": {
"must": [
{
"terms": {
"group.keyword": ["1","2","3","4","5","6","7","8","9","10","11"]
}
}
]
}
},
"size":0
}
相對應的 Java 代碼也修改:
Aggregation aggType = Aggregation.of(agg -> agg.terms(t -> t.field("type")));
Aggregation aggGroup = Aggregation.of(agg -> agg.terms(t -> t.field("group").size(groupList.size())
.aggregations("agg_type", aggType));
可以通過 _cluster 的 API 設置此參數。
PUT _cluster/settings
{
"transient": {
"search.max_buckets":100
}
}
此處使用的是 transient ,還可以使用 persistent,他倆的區別就是transient 的配置會在集群重啟之后失效,persistent會持久化保存。
其中這個參數在之前的索引分片分配策略一文中講過了,還沒看過的可以跳過去看一下,鏈接我放下面。
Elasticsearch Index Shard Allocation 索引分片分配策略
本文通過 demo 示例,從發現聚合桶數量丟失,到排查產生丟失的問題,最后通過 size 參數解決聚合桶數量丟失問題的過程。
意外收獲的是一次請求返回聚合桶數量的總數也是可以通過 search.max_buckets設置的。
日常的積累固然重要,熟悉官方文檔中相關 API 的位置也是必不可少的。
工作中你遇到問題是如何排查的呢,會不會查閱官網文檔呢?歡迎在評論區溝通交流,大家一起學習進步!
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-composite-aggregation.html
https://mp.weixin.q?q.com/s/18bz77nwgC_tF8l_jYD3CA
https://mp.weixin.qq.com/s/Rlu-GDNwnAUR3tzJYk?m5Aw
*請認真填寫需求信息,我們會在24小時內與您取得聯系。