使用 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 交互的基本操作。在实际项目中,你可能需要根据具体需求扩展这个基础实现。

相关推荐
风行無痕1 小时前
单机Elasticsearch 8.19.18安全升级到9.4.3的过程
大数据·elasticsearch·搜索引擎
Elastic 中国社区官方博客3 小时前
使用重新设计的 AutoOps 更快地进行 Elasticsearch 问题排查
大数据·运维·前端·人工智能·elasticsearch·搜索引擎·全文检索
阿拉雷️4 小时前
【搜索实战】Spring Boot 3.3 + AI Agent × Elasticsearch:让AI自动优化搜索策略,查询速度从2秒压到50毫秒
人工智能·spring boot·elasticsearch
阿里云大数据AI技术18 小时前
阿里云 ES AI 引擎版:面向 Agent 场景,为亿级租户、千亿规模向量设计的搜索引擎
人工智能·elasticsearch·agent
阿里云大数据AI技术19 小时前
FalconSeek 技术解析:阿里云 Elasticsearch 云原生内核如何让查询性能飙升600%
人工智能·elasticsearch
Elastic 中国社区官方博客19 小时前
将你的 Grafana Kubernetes 仪表板迁移到 Elastic Observability:相同的 PromQL,30 倍更快的查询
大数据·人工智能·elasticsearch·搜索引擎·容器·kubernetes·grafana
Elasticsearch21 小时前
使用重新设计的 AutoOps 更快地进行 Elasticsearch 问题排查
elasticsearch
Elastic 中国社区官方博客1 天前
如何使用 OpenTelemetry 对你的搜索 API 进行埋点,并使用 ES|QL 对其进行查询
大数据·功能测试·elasticsearch·搜索引擎·全文检索·可用性测试
菜地里的小菜鸟2 天前
logstash定时同步elasticsearch数据
elasticsearch·数据同步·logstash定时同步elastics
BerryS3N2 天前
Code Git 工作树:多分支开发的痛点与工作树的曙光
大数据·git·elasticsearch