使用 C++ 调用 Elasticsearch API

这个示例使用了 libcurl 库进行 HTTP 请求和 nlohmann/json 库处理 JSON 数据:

```cpp

#include <iostream>

#include <string>

#include <curl/curl.h>

#include <nlohmann/json.hpp>

using json = nlohmann::json;

// libcurl 的回调函数,用于收集响应数据

static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {

((std::string*)userp)->append((char*)contents, size * nmemb);

return size * nmemb;

}

// Elasticsearch 客户端类

class ElasticsearchClient {

private:

std::string host;

CURL* curl;

public:

ElasticsearchClient(const std::string& host = "http://localhost:9200") : host(host) {

curl_global_init(CURL_GLOBAL_DEFAULT);

curl = curl_easy_init();

if (!curl) {

throw std::runtime_error("Failed to initialize cURL");

}

}

~ElasticsearchClient() {

if (curl) curl_easy_cleanup(curl);

curl_global_cleanup();

}

// 执行 HTTP 请求

json performRequest(const std::string& method,

const std::string& endpoint,

const json& body = json()) {

std::string responseString;

std::string url = host + endpoint;

// 设置 cURL 选项

curl_easy_setopt(curl, CURLOPT_URL, url.c_str());

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);

curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseString);

curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, method.c_str());

// 设置请求体(如果有)

std::string bodyString = body.dump();

if (!bodyString.empty() && bodyString != "null") {

curl_easy_setopt(curl, CURLOPT_POSTFIELDS, bodyString.c_str());

struct curl_slist* headers = nullptr;

headers = curl_slist_append(headers, "Content-Type: application/json");

curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

}

// 执行请求

CURLcode res = curl_easy_perform(curl);

// 检查错误

if (res != CURLE_OK) {

throw std::runtime_error("cURL failed: " + std::string(curl_easy_strerror(res)));

}

// 解析 JSON 响应

if (!responseString.empty()) {

return json::parse(responseString);

}

return json();

}

// 创建索引

bool createIndex(const std::string& indexName) {

try {

auto response = performRequest("PUT", "/" + indexName);

return response.value("acknowledged", false);

} catch (...) {

return false;

}

}

// 索引文档

std::string indexDocument(const std::string& indexName, const json& document) {

try {

auto response = performRequest("POST", "/" + indexName + "/_doc", document);

return response.value("_id", "");

} catch (...) {

return "";

}

}

// 搜索文档

json searchDocuments(const std::string& indexName, const json& query) {

try {

return performRequest("GET", "/" + indexName + "/_search", query);

} catch (...) {

return json();

}

}

};

int main() {

try {

ElasticsearchClient es;

// 1. 创建索引

std::string indexName = "cplusplus_test";

if (es.createIndex(indexName)) {

std::cout << "索引创建成功: " << indexName << std::endl;

} else {

std::cout << "索引创建失败" << std::endl;

return 1;

}

// 2. 索引文档

json doc1 = {

{"title", "C++ Programming"},

{"content", "Guide to modern C++ features"},

{"year", 2023},

{"tags", json::array({"c++", "programming", "guide"})}

};

json doc2 = {

{"title", "Elasticsearch with C++"},

{"content", "How to use Elasticsearch in C++ applications"},

{"year", 2024},

{"tags", json::array({"c++", "elasticsearch", "api"})}

};

std::string id1 = es.indexDocument(indexName, doc1);

std::string id2 = es.indexDocument(indexName, doc2);

std::cout << "文档1 ID: " << id1 << "\n文档2 ID: " << id2 << std::endl;

// 等待索引刷新(生产环境中应使用更可靠的方式)

sleep(1);

// 3. 执行搜索

json searchQuery = {

{"query", {

{"match", {

{"content", "C++"}

}}

}},

{"size", 10}

};

auto searchResults = es.searchDocuments(indexName, searchQuery);

// 处理搜索结果

if (!searchResults.empty()) {

std::cout << "\n搜索结果 (" << searchResults["hits"]["total"]["value"] << " 个匹配):" << std::endl;

for (const auto& hit : searchResults["hits"]["hits"]) {

std::cout << "\nID: " << hit["_id"]

<< "\n得分: " << hit["_score"]

<< "\n标题: " << hit["_source"]["title"]

<< "\n内容: " << hit["_source"]["content"]

<< "\n年份: " << hit["_source"]["year"]

<< "\n标签: ";

for (const auto& tag : hit["_source"]["tags"]) {

std::cout << tag << " ";

}

std::cout << "\n------------------------------------" << std::endl;

}

} else {

std::cout << "未找到结果" << std::endl;

}

} catch (const std::exception& e) {

std::cerr << "错误: " << e.what() << std::endl;

return 1;

}

return 0;

}

```

编译和运行说明

  1. **依赖库**:
  • libcurl: HTTP 客户端库

  • nlohmann/json: 单头文件 JSON 库

  1. **安装依赖** (Ubuntu):

```bash

sudo apt-get install libcurl4-openssl-dev

```

  1. **编译命令**:

```bash

g++ -std=c++11 -o elasticsearch_example elasticsearch_example.cpp -lcurl

```

  1. **运行前准备**:
  • 确保 Elasticsearch 在 `http://localhost:9200` 运行

  • 安装 nlohmann/json 头文件(或直接包含单文件版本)

示例功能说明

  1. **创建索引**:
  • 创建一个名为 "cplusplus_test" 的索引
  1. **索引文档**:
  • 添加两个包含 C++ 相关内容的文档

  • 自动生成文档 ID

  1. **执行搜索**:
  • 搜索包含 "C++" 的文档

  • 显示搜索结果(ID、得分、标题、内容、年份和标签)

扩展建议

  1. **错误处理增强**:
  • 添加更详细的错误日志

  • 处理 HTTP 状态码(如 404、500 等)

  1. **连接池管理**:
  • 实现连接复用

  • 添加超时设置

  1. **认证支持**:

```cpp

curl_easy_setopt(curl, CURLOPT_USERPWD, "username:password");

```

  1. **批量操作**:
  • 实现批量索引文档

  • 使用 `_bulk` API

  1. **异步操作**:
  • 使用 libcurl 的多接口实现异步请求

  • 或使用线程池

  1. **映射管理**:
  • 添加创建映射的功能

```cpp

json mapping = {

{"mappings", {

{"properties", {

{"title", {{"type", "text"}}},

{"year", {{"type", "integer"}}}

}}

}}

};

performRequest("PUT", "/" + indexName, mapping);

```

  1. **SSL/TLS 支持**:

```cpp

curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); // 禁用证书验证(仅测试用)

curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);

```

这个示例展示了如何用 C++ 与 Elasticsearch 交互的基本操作。在实际项目中,你可能需要根据具体需求扩展这个基础实现。

相关推荐
是小pa丫3 小时前
ElasticSearch重置密码
elasticsearch
南城尽相思5 小时前
es的自定义词典和停用词
elasticsearch·搜索引擎
寅鸷16 小时前
es里为什么node和shard不是一对一的关系
大数据·elasticsearch
阿里云大数据AI技术1 天前
如何在 Elasticsearch 中构建你的智能 AI 助手?
运维·人工智能·elasticsearch
risc1234561 天前
【Lucene/Elasticsearch】**Query Rewrite** 机制
elasticsearch·jenkins·lucene
risc1234562 天前
【Elasticsearch】function_score与rescore
elasticsearch
mit6.8242 天前
[es自动化更新] Updatecli编排配置.yaml | dockerfilePath值文件.yml
大数据·elasticsearch·搜索引擎·自动化
Jinkxs2 天前
Elasticsearch 简介
大数据·elasticsearch·搜索引擎
亮学长2 天前
lodash不支持 Tree Shaking 而 lodash-es可以
大数据·前端·elasticsearch