GitHub Copilot - Elasticsearch 和 MySQL 单表查询耗时比对

当单表数据库超过百万后,数据库 like '%xxx%' 查询明显变慢,为了对比 Elasticsearch 的效果,将百万级的测试数据导入到 Elasticsearch 中对比看看效果。导入和查询 Elasticsearch 的过程完全通过 GitHub Copilot Chat 辅助编码。

Elasticsearch 环境

使用 Docker Compose 快速搭建环境,compose.yaml 配置如下:

version: "2"
services:elasticsearch:image: docker.io/bitnami/elasticsearch:8ports:- '9200:9200'- '9300:9300'volumes:- "elasticsearch_data:/bitnami/elasticsearch"kibana:image: docker.io/bitnami/kibana:8ports:- "5601:5601"volumes:- "kibana_data:/bitnami/kibana"depends_on:- elasticsearch
volumes:elasticsearch_data:driver: localkibana_data:driver: local

参考:

https://github.com/bitnami/containers/tree/main/bitnami/kibana
https://github.com/bitnami/containers/tree/main/bitnami/elasticsearch

数据库 VS Elasticsearch

数据库查询

SQL:

SELECT * FROM itsm_base_enterprisemanagement 
WHERE cname like '%1876%' 
and ctaxcode like '%767%' 
and (ctypeid_name = '6' or ctypeid_name = '16');`

查询结果数:860
查询耗时:3.593s
查询截图:

在这里插入图片描述

Elasticsearch 查询

HTTP:

GET /itsm_base_enterprisemanagement_index/_search
{"size": 10000,"query": {"bool": {"must": [{"wildcard": {"cname": "*1876*"}},{"wildcard": {"ctaxcode": "*767*"}},{"bool": {"should": [{"term": {"ctypeid_name": "6"}},{"term": {"ctypeid_name": "16"}}]}}]}}
}

部分查询结果:

{"took": 78,"timed_out": false,"_shards": {"total": 1,"successful": 1,"skipped": 0,"failed": 0},"hits": {"total": {"value": 860,"relation": "eq"},"max_score": 5.401209,"hits": [{"_index": "itsm_base_enterprisemanagement_index","_id": "1xY-SIwBGWXLItGpKRZG","_score": 5.401209,"_source": {"csynflag": "0","cname": "191618767@qq.com","isvalid": "0","cTimeStamp": "2023-12-06 14:53:41","cCreatorId": "191618767@qq.com","cCreateDate": "2023-12-06 14:53:41","cGuid": "191618767@qq.com","cmaintainerid": "191618767@qq.com","ctypeid_name": "6","ctaxcode": "191618767@qq.com","ccrminsertsyn": "0","ccrmupdatesyn": "1","cremark": "191618767@qq.com191618767"}},

查询结果数:860
查询耗时:155ms
查询截图:

在这里插入图片描述

对比结果: MySQL 比 ES 慢 23 倍

GitHub Copilot 对话过程

<<<GitHub Copilot:

Hi @abel533, how can I help you? I’m powered by AI, so surprises and mistakes are possible. Make sure to verify any generated code or suggestions, and share feedback so that we can learn and improve.

>>>ASK:

JDBC 连接数据库代码。

<<<GitHub Copilot:

要使用 JDBC 连接数据库,您需要以下步骤:

  1. 加载并注册 JDBC 驱动程序
  2. 创建数据库连接
  3. 创建 Statement 对象
  4. 执行 SQL 查询
  5. 处理结果集
  6. 关闭连接

以下是一个简单的示例,该示例使用 JDBC 连接到 MySQL 数据库:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;public class ESInsert {public static void main(String[] args) {String url = "jdbc:mysql://localhost:3306/your_database";String user = "your_username";String password = "your_password";try {// 1. Load and register driverClass.forName("com.mysql.cj.jdbc.Driver");// 2. Create connectionConnection conn = DriverManager.getConnection(url, user, password);// 3. Create statementStatement stmt = conn.createStatement();// 4. Execute SQL query// TODO: Add your SQL query here// 5. Process the result set// TODO: Process your result set here// 6. Close connectionconn.close();} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}}
}

请注意,您需要将 your_database,your_username 和 your_password 替换为您的数据库名称,用户名和密码。此外,您可能需要根据您的实际需求添加 SQL 查询和处理结果集的代码。

>>>ASK:

使用 stmt 查询 itsm_base_enterprisemanagement 表的全部数据,根据表的字段在 ES 创建索引,将所有数据插入到 ES 中。

<<<GitHub Copilot:

要将 itsm_base_enterprisemanagement 表的所有数据查询出来,并根据表的字段在 ES 创建索引,然后将所有数据插入到 ES 中,我们可以按照以下步骤进行:

  1. 使用 stmt 查询 itsm_base_enterprisemanagement 表的所有数据。
  2. 获取查询结果的元数据,以获取列名,这些列名将用作 ES 索引的字段。
  3. 创建 ES 索引。
  4. 将查询结果插入到 ES 索引中。

以下是实现这些步骤的 Java 代码:

import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;// 1. Query all data from itsm_base_enterprisemanagement
String query = "SELECT * FROM itsm_base_enterprisemanagement";
ResultSet rs = stmt.executeQuery(query);// 2. Get the metadata of the result set
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();// 3. Create ES index
String indexName = "itsm_base_enterprisemanagement_index";
CreateIndexRequest request = new CreateIndexRequest(indexName);XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
{builder.startObject("properties");{for (int i = 1; i <= columnCount; i++) {builder.startObject(rsmd.getColumnName(i));{builder.field("type", "text");}builder.endObject();}}builder.endObject();
}
builder.endObject();
request.source(builder);RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))
);
CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);// 4. Insert all data into ES index
while (rs.next()) {Map<String, Object> jsonMap = new HashMap<>();for (int i = 1; i <= columnCount; i++) {jsonMap.put(rsmd.getColumnName(i), rs.getObject(i));}IndexRequest indexRequest = new IndexRequest(indexName).source(jsonMap);IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
}// Don't forget to close the connections
rs.close();
stmt.close();
conn.close();
client.close();

请注意,这段代码假设您已经在项目中添加了 Elasticsearch 的 Java 客户端依赖,并且 Elasticsearch 服务器正在本地的 9200 端口上运行。如果不是,请根据实际情况修改代码。

>>>ASK:

针对 ES 的操作不要使用 elasticsearch-rest-high-level-client sdk,使用 elasticsearch-rest-client 8.11 版本的 sdk

<<<GitHub Copilot:

要使用 elasticsearch-rest-client 8.11 版本的 SDK 进行 ES 操作,我们需要对上述代码进行一些修改。以下是修改后的代码:

import org.apache.http.HttpHost;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;// 1. Query all data from itsm_base_enterprisemanagement
String query = "SELECT * FROM itsm_base_enterprisemanagement";
ResultSet rs = stmt.executeQuery(query);// 2. Get the metadata of the result set
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();// 3. Create ES index
String indexName = "itsm_base_enterprisemanagement_index";RestClientBuilder builder = RestClient.builder(new HttpHost("localhost", 9200, "http"));
RestClient restClient = builder.build();// Create index request
Request createIndexRequest = new Request("PUT", "/" + indexName);
createIndexRequest.setJsonEntity("{\n" +"  \"mappings\": {\n" +"    \"properties\": {\n" +// Add fields to the index"    }\n" +"  }\n" +"}"
);
Response createIndexResponse = restClient.performRequest(createIndexRequest);// 4. Insert all data into ES index
while (rs.next()) {Map<String, Object> jsonMap = new HashMap<>();for (int i = 1; i <= columnCount; i++) {jsonMap.put(rsmd.getColumnName(i), rs.getObject(i));}// Create index requestRequest indexRequest = new Request("POST", "/" + indexName + "/_doc");indexRequest.setJsonEntity(jsonMap.toString());Response indexResponse = restClient.performRequest(indexRequest);
}// Don't forget to close the connections
rs.close();
stmt.close();
conn.close();
restClient.close();

请注意,这段代码假设您的 Elasticsearch 服务器正在本地的 9200 端口上运行。如果不是,请根据实际情况修改代码。此外,这段代码没有处理异常,您可能需要根据实际需求添加异常处理代码。

>>>ASK:

// Add fields to the index,此处注释的属性根据数据库字段自动生成

<<<GitHub Copilot:

要根据数据库字段自动生成索引属性,我们需要在查询结果集的元数据中获取列名,并将这些列名作为索引的字段。以下是修改后的代码:

// 2. Get the metadata of the result set
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();// 3. Create ES index
String indexName = "itsm_base_enterprisemanagement_index";RestClientBuilder builder = RestClient.builder(new HttpHost("localhost", 9200, "http"));
RestClient restClient = builder.build();StringBuilder mappings = new StringBuilder();
mappings.append("{\n");
mappings.append("  \"mappings\": {\n");
mappings.append("    \"properties\": {\n");// Add fields to the index
for (int i = 1; i <= columnCount; i++) {mappings.append("      \"").append(rsmd.getColumnName(i)).append("\": {\n");mappings.append("        \"type\": \"text\"\n");mappings.append("      },\n");
}// Remove the last comma and close the JSON object
mappings.setLength(mappings.length() - 2);
mappings.append("\n    }\n  }\n}");// Create index request
Request createIndexRequest = new Request("PUT", "/" + indexName);
createIndexRequest.setJsonEntity(mappings.toString());
Response createIndexResponse = restClient.performRequest(createIndexRequest);

这段代码将遍历结果集的元数据,获取每个列的名称,并将这些名称作为 ES 索引的字段。然后,它将创建一个包含这些字段的 ES 索引。

>>>ASK:

type 类型不要固定为 text,根据数据库字段类型进行转换。

<<<GitHub Copilot:

要根据数据库字段类型进行转换,我们需要获取结果集元数据中的每个列的类型,并将这些类型用作 ES 索引的字段类型。以下是修改后的代码:

// 2. Get the metadata of the result set
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();// 3. Create ES index
String indexName = "itsm_base_enterprisemanagement_index";RestClientBuilder builder = RestClient.builder(new HttpHost("localhost", 9200, "http"));
RestClient restClient = builder.build();StringBuilder mappings = new StringBuilder();
mappings.append("{\n");
mappings.append("  \"mappings\": {\n");
mappings.append("    \"properties\": {\n");// Add fields to the index
for (int i = 1; i <= columnCount; i++) {mappings.append("      \"").append(rsmd.getColumnName(i)).append("\": {\n");mappings.append("        \"type\": \"").append(convertSqlTypeToESType(rsmd.getColumnType(i))).append("\"\n");mappings.append("      },\n");
}// Remove the last comma and close the JSON object
mappings.setLength(mappings.length() - 2);
mappings.append("\n    }\n  }\n}");// Create index request
Request createIndexRequest = new Request("PUT", "/" + indexName);
createIndexRequest.setJsonEntity(mappings.toString());
Response createIndexResponse = restClient.performRequest(createIndexRequest);

这段代码将遍历结果集的元数据,获取每个列的名称和类型,并将这些名称和类型作为 ES 索引的字段和类型。然后,它将创建一个包含这些字段和类型的 ES 索引。
请注意,我添加了一个名为 convertSqlTypeToESType 的方法,该方法将 SQL 类型转换为 ES 类型。这是该方法的一个简单实现:

private static String convertSqlTypeToESType(int sqlType) {switch (sqlType) {case Types.INTEGER:case Types.TINYINT:case Types.SMALLINT:case Types.BIGINT:return "integer";case Types.FLOAT:case Types.REAL:case Types.DOUBLE:case Types.NUMERIC:case Types.DECIMAL:return "float";case Types.BOOLEAN:return "boolean";case Types.DATE:case Types.TIME:case Types.TIMESTAMP:return "date";default:return "text";}
}

这个方法根据 SQL 类型返回对应的 ES 类型。如果 SQL 类型不在这个方法处理的范围内,那么默认返回"text"。您可能需要根据实际需求修改这个方法。

>>>ASK:

new Request("POST", "/" + indexName + "/\_doc") 这里能否改为批量插入?

<<<GitHub Copilot:

是的,Elasticsearch REST Client 支持批量插入操作。我们可以使用"_bulk" API 来进行批量插入。以下是修改后的代码:

// 4. Insert all data into ES index
StringBuilder bulkRequestBody = new StringBuilder();
while (rs.next()) {Map<String, Object> jsonMap = new HashMap<>();for (int i = 1; i <= columnCount; i++) {jsonMap.put(rsmd.getColumnName(i), rs.getObject(i));}// Create index requestbulkRequestBody.append("{\"index\":{\"_index\":\"").append(indexName).append("\"}}\n");bulkRequestBody.append(jsonMap.toString()).append("\n");
}// Execute bulk request
Request bulkRequest = new Request("POST", "/_bulk");
bulkRequest.setJsonEntity(bulkRequestBody.toString());
Response bulkResponse = restClient.performRequest(bulkRequest);

这段代码将遍历结果集,为每一行数据创建一个索引请求,并将这些请求添加到批量请求的主体中。然后,它将执行批量请求,将所有数据一次性插入到 ES 索引中。

>>>ASK:

批量插入改为每 100 个提交一次

<<<GitHub Copilot:

要实现每 100 条数据提交一次的批量插入,我们可以在遍历结果集时,每当累计到 100 条数据时,就执行一次批量请求。以下是修改后的代码:

// 4. Insert all data into ES index
StringBuilder bulkRequestBody = new StringBuilder();
int count = 0;
while (rs.next()) {Map<String, Object> jsonMap = new HashMap<>();for (int i = 1; i <= columnCount; i++) {jsonMap.put(rsmd.getColumnName(i), rs.getObject(i));}// Create index requestbulkRequestBody.append("{\"index\":{\"_index\":\"").append(indexName).append("\"}}\n");bulkRequestBody.append(jsonMap.toString()).append("\n");count++;// Execute bulk request every 100 recordsif (count % 100 == 0) {Request bulkRequest = new Request("POST", "/_bulk");bulkRequest.setJsonEntity(bulkRequestBody.toString());Response bulkResponse = restClient.performRequest(bulkRequest);// Clear the bulk request bodybulkRequestBody.setLength(0);}
}// Execute the remaining requests if there are less than 100
if (bulkRequestBody.length() > 0) {Request bulkRequest = new Request("POST", "/_bulk");bulkRequest.setJsonEntity(bulkRequestBody.toString());Response bulkResponse = restClient.performRequest(bulkRequest);
}

这段代码将遍历结果集,为每一行数据创建一个索引请求,并将这些请求添加到批量请求的主体中。每当累计到 100 条数据时,它就会执行一次批量请求。如果最后还剩下少于 100 条数据,它也会执行一次批量请求,以确保所有数据都被插入到 ES 索引中。

>>>ASK:

itsm_base_enterprisemanagement 表有 100 多万数据,将查询改为流式查询,每次加载一部分,避免内存不足。

<<<GitHub Copilot:

要将查询改为流式查询,我们可以使用 JDBC 的 Statement 对象的 setFetchSize 方法来设置每次从数据库中获取的行数。以下是修改后的代码:

// 1. Query all data from itsm_base_enterprisemanagement
String query = "SELECT * FROM itsm_base_enterprisemanagement";// Set the fetch size to a reasonable number to avoid memory issues
stmt.setFetchSize(1000);ResultSet rs = stmt.executeQuery(query);

在这段代码中,我们设置了每次从数据库中获取 1000 行数据。这样,即使 itsm_base_enterprisemanagement 表有 100 多万数据,我们也可以避免一次性加载所有数据导致的内存不足问题。

>>>ASK:

在 mysql jdbc 中,设置 1000 有效吗?是否应该 stmt.setFetchSize(Integer.MIN_VALUE);

<<<GitHub Copilot:

在 MySQL JDBC 驱动中,setFetchSize(Integer.MIN_VALUE)被用来开启流式查询,这样可以避免一次性加载所有数据导致的内存不足问题。这是因为 MySQL JDBC 驱动对 setFetchSize 方法的实现与 JDBC 规范不同。在 JDBC 规范中,setFetchSize 方法的参数表示每次从数据库中获取的行数,但在 MySQL JDBC 驱动中,如果参数为 Integer.MIN_VALUE,则会开启流式查询。

如果你想每次从数据库中获取固定数量的行,例如 1000 行,你可以尝试设置 setFetchSize(1000),但是需要注意的是,这在 MySQL JDBC 驱动中可能不会按预期工作,因为 MySQL JDBC 驱动的实现与 JDBC 规范不同。

所以,如果你正在使用 MySQL JDBC 驱动,并且想要开启流式查询以处理大量数据,你应该使用 stmt.setFetchSize(Integer.MIN_VALUE);

>>>ASK:

如何在 kibana 的 devtool 中查询 itsm_base_enterprisemanagement_index 的数量

<<<GitHub Copilot:

要在 Kibana 的 DevTools 中查询 itsm_base_enterprisemanagement_index 的数量,您可以使用 Elasticsearch 的 count API。以下是查询语句:

GET /itsm_base_enterprisemanagement_index/_count

这个查询将返回 itsm_base_enterprisemanagement_index 索引中的文档数量。

>>>ASK:

查询 itsm_base_enterprisemanagement_index 索引中 cname 字段包含 1876 的所有数据的 cguid

<<<GitHub Copilot:

要查询 itsm_base_enterprisemanagement_index 索引中 cname 字段包含 1876 的所有数据的 cguid,您可以使用 Elasticsearch 的 match 查询。在 Kibana 的 DevTools 中,您可以使用以下查询:

GET /itsm_base_enterprisemanagement_index/_search
{"query": {"match": {"cname": "1876"}},"_source": ["cguid"]
}

这个查询将返回 cname 字段包含 1876 的所有文档的 cguid 字段。

>>>ASK:

上面的查询结果为空,为了验证里面有没有数据,先写个查询,获取该索引 10 条数据。

<<<GitHub Copilot:

要查询 itsm_base_enterprisemanagement_index 索引的前 10 条数据,您可以使用 Elasticsearch 的 size 参数来限制返回的文档数量。在 Kibana 的 DevTools 中,您可以使用以下查询:

GET /itsm_base_enterprisemanagement_index/_search
{"size": 10
}

这个查询将返回 itsm_base_enterprisemanagement_index 索引的前 10 条文档。

>>>ASK:

索引中没有任何数据,请检查 ESInsert.java 中是否存在问题?

<<<GitHub Copilot:

首先,我们需要确认以下几点:

  1. 数据库连接信息是否正确?请检查url、user和password是否正确。
  2. 数据库中的itsm_base_enterprisemanagement表是否存在,并且是否有数据?
  3. Elasticsearch服务器是否在运行,并且是否可以通过localhost:9200访问?
  4. 是否有足够的权限在Elasticsearch中创建索引和插入数据?

如果以上所有条件都满足,那么ESInsert.java应该能够正确地从数据库中获取数据并插入到Elasticsearch中。

然而,如果在运行ESInsert.java时抛出了异常,那么可能会在插入数据之前就终止了程序,导致Elasticsearch中没有数据。为了找出可能的问题,你可以检查是否有异常被抛出。在ESInsert.java的main方法中,所有的异常都被捕获并重新抛出为RuntimeException,你可以在重新抛出异常之前打印出异常的详细信息:

} catch (Exception e) {e.printStackTrace();throw new RuntimeException(e);
}

这样,如果有异常被抛出,你就可以在控制台看到异常的详细信息,这将有助于你找出问题所在。

>>>ASK:

我发现 bug 了,在 jsonMap.toString() 这里,这里没有转换为 JSON,导致插入数据出错。

<<<GitHub Copilot:

确实,jsonMap.toString()并不会将 Map 对象转换为 JSON 格式的字符串,而是将其转换为默认的字符串表示形式,这可能会导致插入数据时出错。为了解决这个问题,我们可以使用一个 JSON 库,如 Gson,来将 Map 对象转换为 JSON 格式的字符串。

首先,需要在项目的 pom.xml 文件中添加 Gson 的依赖:

<dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.9</version>
</dependency>

然后,我们可以在 ESInsert.java 文件中使用 Gson 来转换 Map 对象:

import com.google.gson.Gson;// ...public class ESInsert {// ...public static void main(String[] args) {// ...Gson gson = new Gson();// ...while (rs.next()) {Map<String, Object> jsonMap = new HashMap<>();for (int i = 1; i <= columnCount; i++) {jsonMap.put(rsmd.getColumnName(i), rs.getObject(i));}// Create index requestbulkRequestBody.append("{\"index\":{\"_index\":\"").append(indexName).append("\"}}\n");bulkRequestBody.append(gson.toJson(jsonMap)).append("\n");// ...}// ...}// ...
}

在这段修改后的代码中,我们创建了一个 Gson 对象,并使用 gson.toJson(jsonMap)来将 Map 对象转换为 JSON 格式的字符串。

>>>ASK:

为了测试插入索引一些数据,如何使用 HTTP 命令清除索引 itsm_base_enterprisemanagement_index 的所有数据?

<<<GitHub Copilot:

要使用 HTTP 命令清除索引 itsm_base_enterprisemanagement_index 的所有数据,您可以使用 Elasticsearch 的 delete API。在 Kibana 的 DevTools 中,您可以使用以下命令:

DELETE /itsm_base_enterprisemanagement_index

这个命令将删除整个 itsm_base_enterprisemanagement_index 索引,包括索引中的所有数据。如果您想再次插入数据,您需要重新创建索引。

>>>ASK:

如何使用 HTTP 请求,模糊查询 cName 包含 1867 的所有数据,查询结果只返回 cGuid?

<<<GitHub Copilot:

要使用 HTTP 请求模糊查询 cName 包含 1867 的所有数据,并且只返回 cGuid,你可以使用 Elasticsearch 的 match 查询和_source 字段来限制返回的字段。在 Kibana 的 DevTools 中,你可以使用以下查询:

GET /itsm_base_enterprisemanagement_index/_search
{"query": {"match": {"cName": "1867"}},"_source": ["cGuid"]
}

这个查询将返回 cName 字段包含 1867 的所有文档的 cGuid 字段。

>>>ASK:

match是模糊匹配吗?为什么查询不到结果?

<<<GitHub Copilot:

Elasticsearch中的match查询实际上是全文本查询,它不仅可以进行模糊匹配,还会对查询的文本进行分析。这意味着,如果你的字段是被分析的(默认情况下,字符串字段会被分析),那么match查询会在执行查询之前,先将查询的文本分割成单个的词条(或称为tokens),然后对每个词条进行查询。 如果你的查询没有返回结果,可能有以下几个原因:

  1. 你查询的文本在字段中不存在。请检查你的查询文本是否正确。
  2. 你的字段是一个未分析的字段。未分析的字段不会被分割成词条,因此match查询可能无法找到匹配的结果。如果你的字段是未分析的,你可能需要使用term查询。
  3. 你的字段是一个数字或日期字段。match查询主要用于文本字段,对于数字或日期字段,你可能需要使用range查询。

如果你确定你的查询文本在字段中应该存在,但是match查询仍然返回空结果,你可能需要检查你的字段是否被正确地分析。你可以使用_analyze API来测试Elasticsearch如何分析你的字段。

>>>ASK:

如何使用 1435 匹配 191435267@qq.com 和 191435268@qq.com?

<<<GitHub Copilot:

要匹配包含"1435"的邮箱地址,如"191435267@qq.com"和"191435268@qq.com",您可以使用 Elasticsearch 的 wildcard 查询。在 Kibana 的 DevTools 中,您可以使用以下查询:

GET /itsm_base_enterprisemanagement_index/_search
{"query": {"wildcard": {"email": "*1435*"}}
}

这个查询将返回 email 字段包含"1435"的所有文档。

请注意,wildcard 查询可能会比其他类型的查询更消耗资源,因为它需要检查每个字段值是否匹配给定的模式。因此,如果可能,最好使用其他类型的查询,如 match 查询或 term 查询。

>>>ASK:

上述 GET 查询返回结果的 json 结构的各部分是什么含义?为什么没有返回全部匹配的数据?

<<<GitHub Copilot:

Elasticsearch 的 GET 查询返回的 JSON 结构通常包含以下部分:

  • took:查询执行的时间(以毫秒为单位)。
  • timed_out:如果查询在规定的时间内没有完成,则此值为 true。
  • _shards:这部分包含了关于查询涉及的分片的信息,包括总分片数、成功查询的分片数、失败的分片数等。
  • hits:这部分包含了查询结果的详细信息,包括匹配的文档总数、最高得分以及匹配的文档列表。每个文档包含_index(文档所在的索引名)、_type(文档的类型)、_id(文档的 ID)、_score(文档的得分)以及_source(文档的源数据)。
    默认情况下,Elasticsearch 的查询只返回前 10 条匹配的文档,这是为了提高查询效率和响应速度。如果你想返回更多的匹配文档,你可以在查询中添加 size 参数来指定返回的文档数量。例如,以下查询将返回前 100 条匹配的文档:
GET /itsm_base_enterprisemanagement_index/_search
{"size": 100,"query": {"match": {"cName": "1867"}},"_source": ["cGuid"]
}

请注意,size 参数的最大值是 10000。如果你需要处理超过 10000 条的结果,你可能需要使用 scroll API 或者 search_after 参数。

>>>ASK:

将 SQL 形式的查询转换为 kibana 中的 HTTP 形式:SELECT * FROM itsm_base_enterprisemanagement WHERE cname like '%1876%' and ctaxcode like '%767%' and (ctypeid_name = '6' or ctypeid_name = '16');

<<<GitHub Copilot:

在 Kibana 的 DevTools 中,您可以使用 Elasticsearch 的查询 DSL(Domain Specific Language)来执行复杂的查询。以下是将您的 SQL 查询转换为 Elasticsearch 查询的示例:

GET /itsm_base_enterprisemanagement_index/_search
{"query": {"bool": {"must": [{"wildcard": {"cname": "*1876*"}},{"wildcard": {"ctaxcode": "*767*"}},{"bool": {"should": [{"term": {"ctypeid_name": "6"}},{"term": {"ctypeid_name": "16"}}]}}]}}
}

这个查询将返回 cname 字段包含"1876",ctaxcode 字段包含"767",并且 ctypeid_name 字段为"6"或"16"的所有文档。

请注意,这个查询假设您的索引名为 itsm_base_enterprisemanagement_index。如果不是,请根据实际情况修改查询。

>>>ASK:

"should"和"must"什么区别?还有那些命令?

<<<GitHub Copilot:

在 Elasticsearch 中,bool 查询可以包含 must,should,must_not 和 filter 这四种类型的子查询:

  • must:这些查询必须匹配,以便文档被包含在结果中。这相当于逻辑"AND"。
  • should:这些查询至少有一个必须匹配,以便文档被包含在结果中。这相当于逻辑"OR"。如果没有 must 或 filter 查询,那么至少一个 should 查询必须匹配。
  • must_not:这些查询必须不匹配,以便文档被包含在结果中。这相当于逻辑"NOT"。
  • filter:这些查询必须匹配,但它们以不评分、缓存方式贡献于结果。这对于过滤和缓存常见的过滤条件非常有用。
    以下是一个包含所有这些子查询的 bool 查询的示例:
GET /_search
{"query": {"bool": {"must": [{ "match": { "title": "Search" } }],"filter": [{ "term": { "status": "published" } },{ "range": { "publish_date": { "gte": "2015-01-01" }}}],"must_not": [{ "range": { "likes": { "gte": 1000 }}}],"should": [{ "match": { "content": "Elasticsearch" }}]}}
}

这个查询将返回标题包含"Search",状态为"published",发布日期在"2015-01-01"之后,喜欢的人数少于 1000,以及内容包含"Elasticsearch"的所有文档。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/218531.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

3.0 kVrms电压隔离: ADUM162N0BRZ、ADUM163N1BRZ、ADUM1281CRZ、ADUM1285CRZ通用多通道隔离(数字隔离器)

一、ADUM162N、ADuM163N 集成故障安全和2、3个反向通道的鲁棒3.0 kV rms六通道数字隔离器 ADuM162N / ADuM163N 均为采用ADI公司iCoupler技术的6通道数字隔离器。这些隔离器件将高速、互补金属氧化物半导体(CMOS)与单芯片空芯变压器技术融为一体&#xff0c;具有优于光耦合器件…

源代码泄密困扰企业?上海迅软DSE助力解决问题

源代码是软件开发最重要的资源&#xff0c;同时也是开发人员思想、经验和工作的结晶。对于软件开发企业来说&#xff0c;实施有效的源代码防泄密措施至关重要&#xff0c;因为源代码文档和程序文档都具有极高的商业价值&#xff0c;属于企业的商业机密。 为了确保企业的源代码…

Java_Mybatis_缓存

缓存 1.概述 Mybatis 缓存&#xff1a;MyBatis 内置了一个强大的事务性查询缓存机制&#xff0c;它可以非常方便地配置和定制 2.会话缓存&#xff08;一级缓存&#xff09; sqlSession 级别的&#xff0c;也就是说&#xff0c;使用同一个 sqlSession 查询同一 sql 时&#x…

YOLOv7独家原创改进:SPPF自研创新 | SPPF创新结构,重新设计全局平均池化层和全局最大池化层,增强全局视角信息和不同尺度大小的特征

💡💡💡本文原创自研创新改进:SPPF_improve利用全局平均池化层和全局最大池化层,加入一些全局背景信息和边缘信息,从而获取全局视角信息并减轻不同尺度大小所带来的影响 强烈推荐,适合直接使用,paper创新基本 💡💡💡 在多个数据集验证涨点,尤其对存在多个尺…

大模型的研究新方向:混合专家模型(MoE)

大模型的发展已经到了一个瓶颈期&#xff0c;包括被业内所诟病的罔顾事实而产生的“幻觉”问题、深层次的逻辑理解能力、数学推理能力等&#xff0c;想要解决这些问题就不得不继续增加模型的复杂度。随着不同应用场景的实际需求&#xff0c;大模型的参数会变得越来越大&#xf…

npm安装,idea中启动vue失败

node 设置配置之后&#xff0c;要查询时&#xff0c;会从.npmrc中读取路径 .npmrc自己创建的&#xff08;默认情况下.npmrc会创建在C盘中&#xff09; 我创建的在D:\studay-and-working\node16.14\node_modules\npm中 指定.npmrc文件&#xff0c;因为默认会访问C盘的.npmrc文件…

Docker 安装Apache Superset 并实现汉化和快速入门

什么是Apache Superset Apache Superset是一个现代化的企业级商业智能Web应用程序。Apache Superset 支持用户的各种数据类型可视化和数据分析&#xff0c;支持简单图饼图到复杂的地理空间图表。Apache Superset 是一个轻量级、简单化、直观化、可配置的BI 框架。 Docker 安…

【报错栏】(vue)Module not found: Error: Can‘t resolve ‘element-ui‘ in xxx

Module not found: Error: Cant resolve element-ui in xxx 报错原因是&#xff1a; 未安装 element-ui 依赖 解决&#xff1a; npm install element-ui 运行

C语言 二叉树详解(自我理解版)!!!二叉树的实现

目录 1.树的概念和结构&#xff08;了解&#xff09; 1.1树的概念 1.2关于树的每个组成结构的叫法 1.3树的结构体表示 1.4树在实际中的运用 2.二叉树的概念和结构和实现&#xff08;本期偏重点之一&#xff09; 二叉树的概念 ​编辑 特殊的二叉树 1.完全二叉树 2.满二…

Unity 实现单例模式

目录 基本概念 饿汉模式(推荐) 懒汉模式&#xff1a; 基本概念 单例模式&#xff1a;类只有一个实例&#xff0c;一般使用static来实现单例模式&#xff1b; 比如&#xff1a;有一个Test类,实现了单例&#xff0c;假设这个唯一的实例名为SingTonle,实例在类内被实现并被stat…

MAX/MSP SDK学习09:重要示例1

本示例涉及到单个MSP对象同时使用Signal类型、Message类型的入口&#xff1b;代理入口的使用。 注意&#xff1a;MSP对象的入口默认为代理入口&#xff0c;因此Signal类型、Message类型的数据都可接收&#xff1b; #include "ext.h" #include "ext_obex.h&…

【FPGA图像处理实战】- 图像行缓存设计实现方式一(FIFO)

图像处理中稍复杂点的算法,就需要行缓存,以实现3*3窗口、6*6窗口的数据计算。 本文将介绍使用FIFO来实现图像行缓存的设计,包括关键逻辑分析,源代码实现分享。 一、行缓存功能的设计框架 图像数据一般都是按照从左到右,从上到下,一行行数据的方式发送传输的。 这里以…

机器学习三个基本要素:优化算法

在确定了训练集 D、假设空间 ℱ 以及学习准则后&#xff0c;如何找到最优的模型&#x1d453;(x,θ∗) 就成了一个最优化&#xff08;Optimization&#xff09;问题。机器学习的训练过程其实就是最优化问题的求解过程。 参数与超参数 在机器学习中&#xff0c;优化又可以分为参…

mybatis查询结果resultMap映射vo源码分析

概述 mybatis是一个常用的持久层框架&#xff1b;通常搭配mysql使用&#xff1b; 在将查询结果映射成一个复杂vo的时候&#xff0c;通常会用到resultMap&#xff0c;在其中嵌套association和collection等操作&#xff1b;将一个复杂查询拆分成简单查询&#xff1b; 在vo中的变…

WSL 配置 Docker 内存和 CPU 资源限制

我用的电脑一共有40G内存&#xff0c;最近发现电脑重启后&#xff0c;VmmemWSL 进程很快就会占用一多半的内存&#xff08;20G&#xff09;&#xff0c;电脑中有多个停止运行的容器&#xff0c;正常启动状态的只有一个 MySQL 服务&#xff0c;通过 docker stats 查看占用内存也…

PyCharm安装教程

1.1 为什么要安装python开发环境 上一篇文章我们安装了python&#xff0c;准确来说是python解释器&#xff0c;它没有自带的可视化开发工具&#xff0c;只能通过命令行窗口来执行python代码&#xff0c;这里我们就来下载一个用于python开发的可视化工具——PyCharm。 1.2 PyC…

boost1.55 安装使用教程 windows

第一步 &#xff1a;首先在boost官网上下载库压缩包 添加链接描述 选择自己需要的版本进行下载 解压后执行booststrap.bat 用来生成创建b2.exe 和bjam.exe 拓展&#xff1a;.\b2 --help 了解一下有哪些参数可以配置 默认b2.exe编译后&#xff0c;链接到项目如果出现如下错误…

人工智能基本常识:让深度学习技术更加人性化

近年来&#xff0c;人工智能技术日臻成熟。现在&#xff0c;许多产品和服务都依靠人工智能技术实现自动化和智能化&#xff0c;因此它与我们的日常生活息息相关。无论是为我们带来各种便利的家用设备&#xff0c;还是我们一直在使用的产品制造方式&#xff0c;人工智能的影响无…

低代码开发与传统软件开发:未来趋势与竞争格局

近年来&#xff0c;低代码开发平台的快速发展引起了各行各业的广泛关注。低代码开发平台简化了软件开发的复杂性&#xff0c;提供了更快速、更灵活的开发方式。于是&#xff0c;许多人开始产生一个疑问&#xff1a;未来低代码开发是否会取代传统软件开发&#xff1f;今天这篇文…

nodejs微信小程序+python+PHP沧州地区空气质量数据分析系统-计算机毕业设计推荐 django

本系统不仅主要实现了注册登录&#xff0c;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;城市区域管理&#xff0c;空气状况管理&#xff0c;空气质量管理&#xff0c;系统管理&#xff0c;数据爬取&#xff0c;大屏分析等功能&#xff0c;通过这些功能基本可…