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

相关推荐
在未来等你8 小时前
Elasticsearch面试精讲 Day 15:索引别名与零停机更新
大数据·分布式·elasticsearch·搜索引擎·面试
在未来等你9 小时前
Elasticsearch面试精讲 Day 12:数据建模与字段类型选择
大数据·分布式·elasticsearch·搜索引擎·面试
在未来等你13 小时前
Elasticsearch面试精讲 Day 14:数据写入与刷新机制
大数据·分布式·elasticsearch·搜索引擎·面试
phac12314 小时前
git 如何直接拉去远程仓库的内容且忽略本地与远端不一致的commit
大数据·git·elasticsearch
在未来等你14 小时前
Elasticsearch面试精讲 Day 11:索引模板与动态映射
大数据·分布式·elasticsearch·搜索引擎·面试
哥哥还在IT中14 小时前
Elasticsearch优化从入门到精通
大数据·elasticsearch·搜索引擎
Elastic 中国社区官方博客15 小时前
使用 cloud-native Elasticsearch 与 ECK 运行
大数据·数据库·elasticsearch·搜索引擎·kubernetes·k8s·全文检索
2301_781668611 天前
Elasticsearch 02
大数据·elasticsearch·搜索引擎
赵孝正1 天前
GitLab 分支管理与 Push 问题全解析
大数据·elasticsearch·gitlab
一刀到底2111 天前
springboot3.3.5 集成elasticsearch8.12.2 ssl 通过 SSL bundle name 来实现
网络·elasticsearch·ssl·springboot3