ES C++客戶端安裝及使用

介紹

Elasticsearch , 簡稱 ES ,它是個開源分布式搜索引擎,它的特點有:分布式,零配置,自動發現,索引自動分片,索引副本機制,restful 風格接口,多數據源,自動搜索負載等。它可以近乎實時的存儲、檢索數據;本身擴展性很好,可以擴展到上百臺服務器,處理 PB 級別的數據。 es 也使用 Java 開發并使用 Lucene 作為其核心來實現所有索引和搜索的功能,但是它的目的是通過簡單的 RESTful API 來隱藏 Lucene 的復雜性,從而讓全文搜索變得簡單。
Elasticsearch 是面向文檔 (document oriented) 的,這意味著它可以存儲整個對象或文檔 。然而它不僅僅是存儲,還會索引 (index) 每個文檔的內容使之可以被搜索。在 Elasticsearch 中,你可以對文檔(而非成行成列的數據)進行索引、搜索、排序、過濾。

安裝

安裝?Elasticsearch

# 添加倉庫秘鑰
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add - 
# 上邊的添加方式會導致一個 apt-key 的警告,但是不影響# 添加鏡像源倉庫
echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elasticsearch.list
# 更新軟件包列表
sudo apt update
# 安裝 es
sudo apt-get install elasticsearch=7.17.21
# 啟動 es
sudo systemctl start elasticsearch
# 安裝 ik 分詞器插件
sudo /usr/share/elasticsearch/bin/elasticsearch-plugin install https://get.infini.cloud/elasticsearch/analysis-ik/7.17.21

重新啟動 elasticsearch,查看其是否正常運行

sudo systemctl start elasticsearch
sudo systemctl status elasticsearch.service
設置外網訪問:如果新配置完成的話,默認只能在本機進行訪問。
sudo vim /etc/elasticsearch/elasticsearch.yml
新增配置
network.host: 0.0.0.0
http.port: 9200
cluster.initial_master_nodes: ["node-1"]
瀏覽器訪問 http://自己主機的ip:9200/

安裝 Kibana

Kibana 是 Elasticsearch 的官方數據可視化和管理工具,通常與 Elasticsearch 配合使用。以下是關于它的核心解釋和常見使用場景:

Kibana 的核心作用

  1. 數據可視化:通過圖表、儀表盤(Dashboards)展示 Elasticsearch 中的索引數據,支持柱狀圖、折線圖、地圖、詞云等多種可視化形式。

  2. 數據探索:使用?Discover?功能直接搜索和過濾 Elasticsearch 中的數據,支持全文搜索、字段過濾、時間范圍篩選等。

  3. 索引管理:在?Management?中管理 Elasticsearch 的索引、設置索引生命周期(ILM)、定義字段映射(Mapping)等。

  4. 監控與告警:監控 Elasticsearch 集群的健康狀態(如節點狀態、分片分布),配置告警規則(Alerting),例如磁盤空間不足時觸發通知。

  5. 開發工具:內置?Dev Tools,可直接編寫和執行 Elasticsearch 的 REST API 請求(如?GET /_cat/indices)。

使用 apt 命令安裝 Kibana
sudo apt install kibana
配置 Kibana (可選):

根據需要配置 Kibana。配置文件通常位于 /etc/kibana/kibana.yml。可能需要設置如服務器地址、端口、Elasticsearch URL 等。

sudo vim /etc/kibana/kibana.yml
#添加以下配置
elasticsearch.host: "http://localhost:9200"
server.port: 5601
server.host: "0.0.0.0"
重新啟動 Kibana
sudo systemctl restart kibana
sudo systemctl enable kibana
sudo systemctl status kibana
訪問 Kibana
在瀏覽器中訪問 Kibana ,通常是 http://<your-ip>:5601

ES 客戶端的安裝

代碼: https://github.com/seznam/elasticlient
官網: https://seznam.github.io/elasticlient/index.html
ES C++ 的客戶端選擇并不多, 我們這里使用 elasticlient , 下面進行安裝。
# 克隆代碼
git clone https://github.com/seznam/elasticlient
# 切換目錄
cd elasticlient
# 更新子模塊
git submodule update --init --recursive
# 編譯代碼
mkdir build
cd build
# 需要安裝 MicroHTTPD 庫
sudo apt-get install libmicrohttpd-dev
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
make
# 安裝
make install

ES 核心概念

索引(Index

一個索引就是一個擁有幾分相似特征的文檔的集合,類似數據庫中的“庫” 。比如說,你可以有一個客戶數據的索引,一個產品目錄的索引,還有一個訂單數據的索引。一個索引由一個名字來標識(必須全部是小寫字母的),并且當我們要對應于這個索引中的文檔進行索引、搜索、更新和刪除的時候,都要使用到這個名字。在一個集群中,可以定義任意多的索引。

類型(Type

在一個索引中,你可以定義一種或多種類型。一個類型是你的索引的一個邏輯上的分類/分區,其語義完全由你來定,類似數據庫中的“表” 。通常,會為具有一組共同字段的文檔定義一個類型。比如說,我們假設你運營一個博客平臺并且將你所有的數據存儲到一個索引中。在這個索引中,你可以為用戶數據定義一個類型,為博客數據定義另一個類型,為評論數據定義另一個類型。不過在? 7.x 版本后已棄用。

字段(Field

字段相當于是數據表的字段,對文檔數據根據不同屬性進行的分類標識。
分類
類型
備注
字符串
text, keyword
text 會被分詞生成索引,keyword 不會被分詞生成索引,只能精確值搜索
整形
integer, long, short, byte
浮點
double float
邏輯
boolean
true false
日期
date, date_nanos“2018-01-13” 或 “2018-01-13 12:10:30”
或者時間戳,即 1970 到現在的秒數 / 毫秒數
二進制
binary
二進制通常只存儲,不索引
范圍
range

映射(mapping

映射是在處理數據的方式和規則方面做一些限制,如某個字段的數據類型、默認值、分析器、是否被索引等等,這些都是映射里面可以設置的,其它就是處理 es 里面數據的一些使用規則設置也叫做映射,按著最優規則處理數據對性能提高很大,因此才需要建立映射,并且需要思考如何建立映射才能對性能更好。
名稱
數值
備注
enabled
true(默認) | false
是否僅作存儲,不做搜索和分析
index
true( 默認 ) | false
是否構建倒排索引(決定了是否分詞,是否被索引)
index_option
dynamic
true(默認)| false
控制 mapping 的自動更新
doc_value
true(默認) | false
是否開啟 doc_value ,用戶聚合和排序分析,分詞字段不能使用
fielddatafielddata: {"format": "disabled"}
是否為 text 類型啟動 fielddata,實現排序和聚合分析。針對分詞字段,參與排序或聚合時能提高性能,不分詞字段統一建議使用 doc_value。
store
true | false(默認)是否單獨設置此字段的存儲而從 _source 字段中分離,只能搜索,不能獲取值
coercetrue(默認) | false是否開啟自動數據類型轉換功能,比如:字符串轉數字,浮點轉整型
analyzer"analyzer": "ik"
指定分詞器,默認分詞器為 standard?analyzer
boost
"boost": 1.23
字段級別的分數加權,默認值是 1.0
fields
"fields": {
????????"raw": {
????????????????"type":"text",
????????????????"index":"not_analyzed"
????????????????}
????????}
對一個字段提供多種索引模式,同一個字段的值,一個分詞,一個不分詞
data_detection
true( 默認 ) | false
是否自動識別日期類型

文檔 (document

一個文檔是一個可被索引的基礎信息單元。比如,你可以擁有某一個客戶的文檔,某一個產品的一個文檔或者某個訂單的一個文檔。文檔以 JSON Javascript Object Notation)格式來表示,而 JSON 是一個到處存在的互聯網數據交互格式。在一個 index/type 里面,你可以存儲任意多的文檔。一個文檔必須被索引或者賦予一個索引的 type
Elasticsearch 與傳統關系型數據庫相比如下:

ES 客戶端的使用示例

在瀏覽器中訪問 Kibana,通常是 http://<your-ip>:5601,在工具頁面進行編碼,使用以下語句:

#創建索引并配置字段和映射
POST /user/_doc
{"settings" : {"analysis" : {"analyzer" : {"ik" : {"tokenizer" : "ik_max_word"}}}},"mappings":{"dynamic" : true,"properties":{"nickname" : {"type" : "text","analyzer" : "ik_max_word"},"user_id" : {"type" : "keyword","analyzer" : "standard"},"phone" : {"type" : "keyword","analyzer" : "standard"},"description" : {"type" : "text","enabled" : false},"avatar_id":{"type" : "keyword","enabled" : false}}}
}
#新增數據
POST /user/_doc/_bulk
{"index":{"_id":"1"}}
{"user_id" : "USER4b862aaa-2df8654a-7eb4bb65-e3507f66","nickname" : "昵稱 1","phone" : "手機號 1","description" : "簽名 1","avatar_id" : "頭像 1"}
{"index":{"_id":"2"}}
{"user_id" : "USER14eeeaa5-442771b9-0262e455-e4663d1d","nickname" : "昵稱 2","phone" : "手機號 2","description" : "簽名 2","avatar_id" : "頭像 2"}
{"index":{"_id":"3"}}
{"user_id" : "USER484a6734-03a124f0-996c169d-d05c1869","nickname" : "昵稱 3","phone" : "手機號 3","description" : "簽名 3","avatar_id" : "頭像 3"}
{"index":{"_id":"4"}}
{"user_id" : "USER186ade83-4460d4a6-8c08068f-83127b5d","nickname" : "昵稱 4","phone" : "手機號 4","description" : "簽名 4","avatar_id" : "頭像 4"}
{"index":{"_id":"5"}}
{"user_id" : "USER6f19d074-c33891cf-23bf5a83-57189a19","nickname" : "昵稱 5","phone" : "手機號 5","description" : "簽名 5","avatar_id" : "頭像 5"}
{"index":{"_id":"6"}}
{"user_id" : "USER97605c64-9833ebb7-d0455353-35a59195","nickname" : "昵稱 6","phone" : "手機號 6","description" : "簽名 6","avatar_id" : "頭像 6"}

main.cc

#include <elasticlient/client.h>
#include <cpr/cpr.h>
#include <iostream>
int main()
{// 1. 構建ES客戶端elasticlient::Client client({"http://127.0.0.1:9200/"});// 2. 發起搜索請求try{auto rsp = client.search("user", "_doc", "{\"query\":{\"match_all\":{}}}");std::cout << rsp.status_code << std::endl;std::cout << rsp.text << std::endl;}catch (const std::exception &e){std::cerr << "請求失敗:" << e.what() << '\n';return -1;}return 0;
}

makefile

main : main.ccg++ -o $@ $^ -std=c++17 -lcpr -lelasticlient

ES 客戶端 API 二次封裝

封裝客戶端 api 主要是因為,客戶端只提供了基礎的數據存儲獲取調用功能,無法根據我們的思想完成索引的構建,以及查詢正文的構建,需要使用者自己組織好 json 進行序列化后才能作為正文進行接口的調用。而封裝的目的就是簡化用戶的操作,將索引的 json 正文構造,以及查詢搜索的正文構造操作給封裝起來,使用者調用接口添加字段就行,不用關心具體的 json 數據格式。
封裝內容:
  • 索引構造過程的封裝:索引正文構造過程,大部分正文都是固定的,唯一不同的地方是各個字段不同的名稱以及是否只存儲不索引這些選項,因此重點關注以下幾個點即可:
  1. 字段類型:type : text / keyword (目前只用到這兩個類型)
  2. 是否索引:enable : true/false
  3. 索引的話分詞器類型: analyzer : ik_max_word / standard
  • 新增文檔構造過程的封裝:新增文檔其實在常規下都是單條新增,并非批量新增,因此直接添加字段和值就行
  • 文檔搜索構造過程的封裝:搜索正文構造過程,我們默認使用條件搜索,我們主要關注的兩個點:
  1. 應該遵循的條件是什么:should 中有什么
  2. 條件的匹配方式是什么:match 還是 term/terms,還是 wildcard
  3. 過濾的條件字段是什么:must_not 中有什么
  4. 過濾的條件字段匹配方式是什么:match 還是 wildcard,還是 term/terms
整個封裝的過程其實就是對 Json::Value 對象的一個組織的過程,并無太大的難點。
#pragma once
#include <elasticlient/client.h>
#include <json/json.h>
#include <iostream>
#include <memory>
#include <sstream>
#include <cpr/cpr.h>
#include "logger.hpp"bool Serialize(const Json::Value &val, std::string &dst)
{// 先定義Json::StreamWriter 工廠類 Json::StreamWriterBuilderJson::StreamWriterBuilder swb;swb.settings_["emitUTF8"] = true;std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());// 通過Json::StreamWriter中的write接口進行序列化std::stringstream ss;int ret = sw->write(val, &ss);if (ret != 0){std::cout << "Json反序列化失敗!\n";return false;}dst = ss.str();return true;
}
bool UnSerialize(const std::string &src, Json::Value &val)
{Json::CharReaderBuilder crb;crb.settings_["emitUTF8"] = true;std::unique_ptr<Json::CharReader> cr(crb.newCharReader());std::string error;bool ret = cr->parse(src.c_str(), src.c_str() + src.size(), &val, &error);if (ret == false){std::cout << "json反序列化失敗: " << error << std::endl;return false;}return true;
}
class ESIndex
{
public:ESIndex(std::shared_ptr<elasticlient::Client> &client,const std::string &name, const std::string &type = "_doc") : _name(name), _type(type), _client(client){Json::Value analysis;Json::Value analyzer;Json::Value ik;Json::Value tokenizer;tokenizer["tokenizer"] = "ik_max_word";ik["ik"] = tokenizer;analyzer["analyzer"] = ik;analysis["analysis"] = analyzer;_index["settings"] = analysis;}ESIndex &append(const std::string &key, const std::string &type = "text",const std::string &analyzer = "ik_max_word", bool enabled = true){Json::Value fields;fields["type"] = type;fields["analyzer"] = analyzer;if (enabled == false)fields["enabled"] = false;_properties[key] = fields;return *this;}bool create(const std::string &index_id = "default_index_id"){Json::Value mappings;mappings["dynamic"] = true;mappings["properties"] = _properties;_index["mappings"] = mappings;std::string body;bool ret = Serialize(_index, body);if (ret == false){LOG_ERROR("索引序列化失敗!");return false;}LOG_DEBUG("{}", body);try{auto rsp = _client->index(_name, _type, index_id, body);if (rsp.status_code < 200 || rsp.status_code >= 300){LOG_ERROR("創建ES索引{}失敗,響應狀態碼異常:{}", _name, rsp.status_code);return false;}}catch (const std::exception &e){LOG_ERROR("創建ES索引{}失敗:{}", _name, e.what());return false;}return true;}private:std::shared_ptr<elasticlient::Client> _client;std::string _name;std::string _type;Json::Value _index;Json::Value _properties;
};class ESInsert
{
public:ESInsert(std::shared_ptr<elasticlient::Client> &client,const std::string &name, const std::string &type = "_doc") : _name(name), _type(type), _client(client){}template <typename T>ESInsert &append(const std::string &key, const T &val){_item[key] = val;return *this;}bool insert(const std::string id = ""){std::string body;bool ret = Serialize(_item, body);if (ret == false){LOG_ERROR("索引序列化失敗!");return false;}LOG_DEBUG("{}", body);try{auto rsp = _client->index(_name, _type, id, body);if (rsp.status_code < 200 || rsp.status_code >= 300){LOG_ERROR("新增數據{}失敗,響應狀態碼異常:{}", body, rsp.status_code);return false;}}catch (const std::exception &e){LOG_ERROR("新增數據{}失敗:{}", body, e.what());return false;}return true;}private:std::shared_ptr<elasticlient::Client> _client;std::string _name;std::string _type;Json::Value _item;
};class ESRemove
{
public:ESRemove(std::shared_ptr<elasticlient::Client> &client,const std::string &name, const std::string &type= "_doc"): _client(client), _name(name), _type(type){}bool remove(const std::string &id){try{auto rsp = _client->remove(_name, _type, id);if (rsp.status_code < 200 || rsp.status_code >= 300){LOG_ERROR("刪除數據{}失敗,響應狀態碼異常:{}", id, rsp.status_code);return false;}}catch (const std::exception &e){LOG_ERROR("刪除數據{}失敗:{}", id, e.what());return false;}return true;}private:std::shared_ptr<elasticlient::Client> _client;std::string _name;std::string _type;
};class ESSearch
{
public:ESSearch(std::shared_ptr<elasticlient::Client> &client,const std::string &name, const std::string &type= "_doc"): _client(client), _name(name), _type(type){}ESSearch &append_must_not_terms(const std::string &key, const std::vector<std::string> &vals){Json::Value fields;for (const auto &val : vals){fields[key].append(val);}Json::Value terms;terms["terms"] = fields;_must_not.append(terms);return *this;}ESSearch &append_must_term(const std::string &key, const std::string &val){Json::Value field;field[key] = val;Json::Value term;term["terms"] = field;_must.append(term);return *this;}ESSearch &append_must_match(const std::string &key, const std::string &val){Json::Value field;field[key] = val;Json::Value match;match["match"] = field;_must.append(match);return *this;}ESSearch &append_should_match(const std::string &key, const std::string &val){Json::Value field;field[key] = val;Json::Value match;match["match"] = field;_should.append(match);return *this;}Json::Value search(){Json::Value cond;if (_must_not.empty() == false)cond["must_not"] = _must_not;if (_must.empty() == false)cond["must"] = _must;if (_should.empty() == false)cond["should"] = _should;Json::Value query;query["bool"] = cond;Json::Value root;root["query"] = query;std::string body;bool ret = Serialize(root, body);if (ret == false){LOG_ERROR("索引序列化失敗!");return Json::Value();}LOG_DEBUG("{}", body);cpr::Response rsp;try{rsp = _client->search(_name, _type, body);if (rsp.status_code < 200 || rsp.status_code >= 300){LOG_ERROR("檢索數據{}失敗,響應狀態碼異常:{}", body, rsp.status_code);return Json::Value();}}catch (const std::exception &e){LOG_ERROR("刪除數據{}失敗:{}", body, e.what());return Json::Value();}LOG_DEBUG("檢索響應正文:{}", rsp.text);Json::Value json_rsp;ret = UnSerialize(rsp.text, json_rsp);if (ret == false){LOG_ERROR("檢索數據 {} 結果反序列化失敗", rsp.text);return Json::Value();}return json_rsp["hits"]["hits"];}private:std::shared_ptr<elasticlient::Client> _client;std::string _name;std::string _type;Json::Value _must_not;Json::Value _must;Json::Value _should;
};

makefile

main : main.cc g++ -std=c++17 $^ -o $@ -lcpr -lelasticlient -lspdlog -lfmt -lgflags -ljsoncpp

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/83242.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/83242.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/83242.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

力扣-94.二叉樹的中序遍歷

題目描述 給定一個二叉樹的根節點 root &#xff0c;返回 它的 中序 遍歷 。 class Solution { public:void inorder(TreeNode* root, vector<int>& res){//C這里&一定要加if(!root)return;inorder(root->left,res);res.push_back(root->val);inorder(ro…

《大模型微調實戰:Llama 3.0全參數優化指南》

全參數微調&#xff08;Full Parameter Fine-Tuning&#xff09;是推動大模型適應垂直領域任務的核心技術&#xff0c;尤其對于Llama 3.0這類千億級參數模型而言&#xff0c;其性能優化與場景適配能力直接決定了實際應用價值。然而&#xff0c;全參數微調面臨計算成本高、內存占…

張 提示詞優化(相似計算模式)深度學習中的損失函數優化技巧

失函數的解釋 損失函數代碼解析 loss = -F.log_softmax(logits[

《Spring Boot 4.0新特性深度解析》

Spring Boot 4.0的發布標志著Java生態向云原生與開發效能革命的全面邁進。作為企業級應用開發的事實標準框架&#xff0c;此次升級在運行時性能、云原生支持、開發者體驗及生態兼容性四大維度實現突破性創新。本文深度解析其核心技術特性&#xff0c;涵蓋GraalVM原生鏡像支持、…

協作賦能-1-制造業生產流程重構

制造業生產流程重構——從“信息孤島”到“全鏈協同” 在制造業的數字化轉型浪潮中&#xff0c;一個看似矛盾的現象正在蔓延&#xff1a;企業部署了ERP、MES、PLM等管理系統&#xff0c;卻仍未擺脫“紙質工單滿天飛、跨部門扯皮不斷”的困境。以汽車制造業為例&#xff0c;其…

基于React的高德地圖api教程002:自定義地圖樣式

文章目錄 2、自定義地圖樣式2.1 自定義底圖樣式2.2 添加衛星地圖和路網圖2.3 完整代碼下載2、自定義地圖樣式 2.1 自定義底圖樣式 高德地圖提供了多種地圖樣式,對底圖進行設置,可選樣式如下圖所示: 添加地圖樣式切換控件: <div style={{marg

谷歌Gemini生圖升級:與GPT-4o的對決,誰更勝一籌?

在人工智能技術的快速發展中&#xff0c;圖像生成&#xff08;即“生圖”&#xff09;已經成為AI領域的一大熱點。谷歌最近對其多模態模型Gemini 2.0 Flash的生圖功能進行了升級&#xff0c;從之前的“實驗版”&#xff08;Gemini 2.0 Flash Experimental Image Generation&…

OpenAI官方指南,詳細解釋了何時使用哪種AI模型

&#xff08;1&#xff09;GPT-4o ? 日常任務專家&#xff1a;頭腦風暴/會議紀要/郵件撰寫/創意生成 ? 全模態支持&#xff1a;兼容GPTs插件/數據分析/圖像生成/畫布協作/高級語音等功能&#xff0c;支持文檔/圖片/CSV/音視頻等多格式輸入 【典型用例】 ? 將會議記錄提煉…

火山引擎發展方向

火山引擎作為字節跳動旗下的企業級技術服務平臺&#xff0c;要發展客戶需要結合自身技術優勢、行業趨勢和市場需求&#xff0c;制定差異化的策略。以下是一些關鍵方向和建議&#xff1a; --- ### **一、明確目標市場定位** 1. **聚焦核心賽道** - **泛互聯網行業**&…

在 Angular 中, `if...else if...else`

在 Angular 中&#xff0c;模板語法本身并不直接支持 if...else if...else 這樣的多條件分支結構。不過&#xff0c;你可以通過使用 *ngIf 指令結合其else模板功能來實現類似的效果。下面是如何模擬if...else if...else邏輯的方法&#xff1a; 示例&#xff1a;實現if...else …

利用Backtrader實現回測策略的可視化與圖表繪制

Plotting功能是Backtrader的一大特色,能夠幫助直觀地展示交易數據、策略表現等信息,為分析和優化交易策略提供有力支持。 (一)Backtrader的主要特點 靈活性:支持多種數據源和交易接口,用戶可以根據自己的需求靈活選擇。無論是股票、期貨、外匯等不同類型的金融市場數據,…

提升英文輸入效率:基于Docker的Qwerty Learner本地搭建與使用指南

文章目錄 前言1.關于qwerty-learner2.Docker部署3.簡單使用演示4.安裝cpolar內網穿透5. 配置公網地址6. 配置固定公網地址總結 前言 小伙伴們&#xff0c;你們有沒有遇到過這種情況&#xff1a;中文輸入流暢自如&#xff0c;一到英文模式就變成了新手司機&#xff1f;別擔心&a…

BUUCTF——shrine

BUUCTF——shrine 進入靶場 只有一串代碼 import flask import os app flask.Flask(__name__) app.config[FLAG] os.environ.pop(FLAG) #程序從環境變量 FLAG 讀取一個敏感值&#xff0c;并存儲在 app.config[FLAG] 中。 #安全問題&#xff1a;如果攻擊者能訪問 app.con…

【Python】對象生命周期全解析

Python對象生命周期全解析 在Python中&#xff0c;一個對象從創建到銷毀會經歷一系列過程&#xff0c;理解這些過程對于編寫高效、可靠的Python代碼非常重要。下面我將詳細講解Python對象的完整生命周期。 1. 對象創建階段 (1) 內存分配 當使用類實例化時(obj MyClass())&…

科學養生指南:解鎖健康生活的密碼

健康是人生最寶貴的財富&#xff0c;科學養生則是守護這筆財富的關鍵。即使拋開傳統中醫理論&#xff0c;現代科學也為我們提供了諸多實用的養生方法。? 合理飲食是健康養生的基石。人體需要碳水化合物、蛋白質、脂肪、維生素和礦物質等多種營養物質維持運轉。日常飲食應遵循…

深入解析 Python 應用日志監控:ELK、Graylog 的實戰指南

深入解析 Python 應用日志監控:ELK、Graylog 的實戰指南 引言 在現代應用開發中,日志不僅僅是用于記錄錯誤和調試信息,它更是系統運行狀況的窗口,幫助開發者和運維人員監控、優化應用性能。Python 作為廣泛應用的開發語言,其應用日志管理的重要性不言而喻。而 ELK(Elas…

【vue】腳手架

一、使用腳手架創建項目 1.打開編輯器終端 2.輸入命令vue create 項目名 3.選擇自定義配置&#xff0c;選以下幾種常用的配置項&#xff08;空格選中或刪除&#xff09; 二、常規操作 進入項目&#xff1a;cd 項目名 返回&#xff1a;cd .. 運行項目:npm run serve 停止項目:ct…

2025全網首發:ComfyUI整合GPT-Image-1完全指南 - 8步實現AI圖像創作革命

ComfyUI整合GPT-Image-1完全指南&#xff1a;8步實現AI圖像創作革命【2025最新】 OpenAI最新發布的GPT-Image-1模型&#xff08;也就是ChatGPT-4o背后的圖像生成技術&#xff09;已經通過API開放使用&#xff0c;而令人驚喜的是&#xff0c;ComfyUI已經第一時間提供了完整支持&…

每日算法刷題計劃Day7 5.15:leetcode滑動窗口4道題,用時1h

一.定長滑動窗口 【套路】教你解決定長滑窗&#xff01;適用于所有定長滑窗題目&#xff01; 模版套路 1.題目描述 1.計算所有長度恰好為 k 的子串中&#xff0c;最多可以包含多少個元音字母 2.找出平均數最大且 長度為 k 的連續子數組&#xff0c;并輸出該最大平均數。 3.…

JavaScript的BOM、DOM編程

參考筆記&#xff1a;JavaWeb 速通DOM_java dom-CSDN博客 目錄 1.JS的組成部分 2.BOM編程 2.1 基本介紹 2.2 BOM的構成 2.3 圖解BOM編程 2.4 windows對象的常見屬性 2.5 windows對象的常見方法 2.6 BOM編程的簡單示例 2.6.1 三種彈窗方式 ?2.6.2 頁面跳轉 2.6.3…