Easysearch 可搜索快照功能,看这篇就够了
yangmf2040 发表了文章 • 0 个评论 • 3103 次浏览 • 2024-12-30 16:38
可搜索快照功能改变了我们对备份数据的查询方式。以往要查询备份数据时,要先找到备份数据所在的快照,然后在一个合适的环境中恢复快照,最后再发起请求查询数据。这个处理路径很长,而且很消耗时间。可搜索快照功能将大大简化该处理路径,节约时间。
角色设置
相信你对节点角色的概念已经有所熟悉。要启用可搜索快照功能,[Easysearch](https://infinilabs.cn/products/easysearch/) 集群中必须至少有一个节点拥有 search 角色。参考设置如下。
plain<br /> node.roles: ["search"]<br /> node.search.cache.size: 500mb<br />
- node.roles: 指定节点角色,只有 search 角色的节点才能去搜索快照中的数据。
- node.search.cache.size: 执行快照搜索时,数据缓存大小。
混合角色设置,参考如下。
plain<br /> node.roles: ["master","data","search","ingest"]<br /> node.search.cache.size: 500mb<br />
创建快照
可搜索快照功能使用普通快照作为基础,创建快照命令不变。比如我创建且备份个 infini 索引。
```plain创建 infini 索引
POST infini/_doc
{
"test":"Searchable snapshots"
}
创建快照备份 infini 索引
PUT _snapshot/my-fs-repository/1
{
"indices": "infini",
"include_global_state": false
}
```

创建快照索引
可搜索快照功能的核心是搜索快照中的索引,这一步是通过快照索引实现的。为了和集群中的普通索引区别开来,我们将实际存储在快照中的索引称为快照索引。通过使用 Easysearch 的 _restore API 并指定 remote_snapshot 存储类型来创建快照索引。
创建快照索引时,注意名称不能与当前索引名称重复。通常我们备份完索引后,可删除索引释放节点磁盘空间,创建快照索引时默认使用原来的名称。
```plain删除 infini 索引释放磁盘空间
DELETE infini
创建快照索引,使用原索引名称
POST /_snapshot/my-fs-repository/1/_restore
{
"indices": "infini",
"include_global_state": false,
"include_aliases": false,
"storage_type": "remote_snapshot"
}
<br /> <br /> 创建快照索引的命令和还原快照的命令非常相似,关键在于 storage_type 参数指定 remote_snapshot 存储类型。<br /> <br /> 如果要将快照中的全部索引都创建快照索引,可省略 indices 参数。<br /> <br /> <br /> <br /> 如果想在创建快照索引时指定不同的名字,参考下面的命令。<br /> <br />
plain
POST /_snapshot/my-fs-repository/1/_restore
{
"indices": "infini",
"include_global_state": false,
"include_aliases": false,
"storage_type": "remote_snapshot",
"rename_pattern": "(infini)",
"rename_replacement": "snapshot-$1"
}
```
- rename_pattern: 使用此选项指定索引匹配的正则表达式。使用捕获组重用索引名称的部分。
- rename_replacement: 使用 $0 包括整个匹配索引名称,使用 $1 包括第一个捕获组的内容,等等。
上述命令创建出来的快照索引名称是 snapshot-infini 。

经过上面一系列的操作,我已经拥有了两个快照索引。
搜索快照索引
我们通过搜索快照索引达到搜索快照数据的目的,令人开心的是搜索快照索引和搜索普通索引的语法完全一样。😀

常见问题
如何区分普通索引和快照索引呢?
我们可以通过索引的 settings 信息区分,快照索引的 settings 信息中有 store.type: remote_snapshot 信息,普通索引没有此信息。

快照索引能写入数据吗?
快照索引无法写入,数据仍然保持在快照格式中存储在存储库中,因此可搜索快照索引本质上是只读的。 任何尝试写入可搜索快照索引的操作都会导致错误。

快照索引不想要了怎么办?
直接删除,需要时再执行创建快照索引流程。此外快照在创建快照索引后,无法直接删除快照,要先删除快照索引。

如果您对上述内容有任何疑问,欢迎与我讨论。

Spring Boot 集成 Easysearch 完整指南
INFINI Labs 小助手 发表了文章 • 0 个评论 • 3465 次浏览 • 2024-12-29 15:41
[Easysearch](https://infinilabs.cn/products/easysearch/) 的很多用户都有这样的需要,之前是用的 ES,现在要迁移到 Easysearch,但是业务方使用的是 Spring Boot 集成的客户端,问是否能平滑迁移。
Easysearch 是完全兼容 Spring Boot 的,完全不用修改,本指南将探讨如何将 Spring Boot 和 ES 的 high-level 客户端 与 Easysearch 进行集成,涵盖从基础设置到实现 CRUD 操作和测试的所有内容。
服务器设置
首先,需要修改 Easysearch 节点的 easysearch.yml 文件,打开并配置这 2 个配置项:
```yml
elasticsearch.api_compatibility: true
根据客户端版本配置版本号,我这里配置成 7.17.18
elasticsearch.api_compatibility_version: "7.17.18"
```
项目设置
然后,让我们设置 Maven 依赖。以下是 pom.xml
中的基本配置:
```xml
```
## 客户端连接配置
完全和连接 Elasticsearch 的方式一样,不用修改:
配置 src/main/resources/application.yml 文件
```yaml
spring:
elasticsearch:
rest:
uris: https://localhost:9202
username: admin
password: xxxxxxxxxxx
ssl:
verification-mode: none
```
连接配置类
```java
@Configuration
public class ElasticsearchConfig extends AbstractElasticsearchConfiguration {
@Value("${spring.elasticsearch.rest.uris}")
private String elasticsearchUrl;
@Value("${spring.elasticsearch.rest.username}")
private String username;
@Value("${spring.elasticsearch.rest.password}")
private String password;
@Override
@Bean
public RestHighLevelClient elasticsearchClient() {
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials(username, password));
SSLContext sslContext = SSLContexts.custom()
.loadTrustMaterial(null, (x509Certificates, s) -> true)
.build();
RestClientBuilder builder = RestClient.builder(HttpHost.create(elasticsearchUrl))
.setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder
.setDefaultCredentialsProvider(credentialsProvider)
.setSSLContext(sslContext)
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE));
return new RestHighLevelClient(builder);
}
}
```
## 领域模型
使用 Spring 的 Elasticsearch 注解定义领域模型:
```java
@Data
@Document(indexName = "products")
public class Product {
@Id
private String id;
@Field(type = FieldType.Text, name = "name")
private String name;
@Field(type = FieldType.Double, name = "price")
private Double price;
}
```
## 仓库层
创建继承 ElasticsearchRepository 的仓库接口:
```java
@Repository
@EnableElasticsearchRepositories
public interface ProductRepository extends ElasticsearchRepository
}
```
## 服务层
实现服务层来处理业务逻辑:
```java
@Service
public class ProductService {
private final ProductRepository productRepository;
@Autowired
public ProductService(ProductRepository productRepository) {
this.productRepository = productRepository;
}
public Product saveProduct(Product product) {
return productRepository.save(product);
}
public Product findProductById(String id) {
return productRepository.findById(id).orElse(null);
}
}
```
## 测试
编写集成测试类:
```java
@SpringBootTest
public class ProductServiceIntegrationTest {
@Autowired
private ElasticsearchOperations elasticsearchOperations;
@Autowired
private ProductService productService;
private static final String INDEX_NAME = "products";
@BeforeEach
public void setUp() {
IndexOperations indexOperations = elasticsearchOperations.indexOps(IndexCoordinates.of(INDEX_NAME));
if (indexOperations.exists()) {
indexOperations.delete();
}
// 定义 mapping
Document mapping = Document.create()
.append("properties", Document.create()
.append("name", Document.create()
.append("type", "text")
.append("analyzer", "standard"))
.append("price", Document.create()
.append("type", "double")));
// 创建索引并应用 mapping
indexOperations.create(Collections.EMPTY_MAP, mapping);
}
@Test
public void testSaveAndFindProduct() {
List
new Product("Test Product 1", 99.99),
new Product("Test Product 2", 199.99),
new Product("Test Product 3", 299.99)
);
List
.map(product -> new IndexQueryBuilder()
.withObject(product)
.withIndex(INDEX_NAME)
.build())
.collect(Collectors.toList());
List
queries,
IndexCoordinates.of(INDEX_NAME)
);
// 验证结果
List
.map(IndexedObjectInformation::getId)
.collect(Collectors.toList());
assertFalse(ids.isEmpty());
assertEquals(products.size(), ids.size());
}
}
```
## 结论
本指南展示了 Easysearch 与 Elasticsearch 的高度兼容性:
1. 配置方式相同,仅需启用 Easysearch 的 API 兼容模式。
2. 可直接使用现有 Elasticsearch 客户端。
3. Maven 依赖无需更改。
4. API、注解和仓库接口完全兼容。
5. 现有测试代码可直接应用。
这种兼容性使得从 Elasticsearch 迁移到 Easysearch 成为一个简单、低风险的过程。Spring Boot 项目可以几乎无缝地切换到 Easysearch,同时获得其性能和资源利用方面的优势。
## 关于 Easysearch

INFINI Easysearch 是一个分布式的搜索型数据库,实现非结构化数据检索、全文检索、向量检索、地理位置信息查询、组合索引查询、多语种支持、聚合分析等。Easysearch 可以完美替代 Elasticsearch,同时添加和完善多项企业级功能。Easysearch 助您拥有简洁、高效、易用的搜索体验。
官网文档:<https://infinilabs.cn/docs/latest/easysearch>
> 作者:张磊,极限科技(INFINI Labs)搜索引擎研发负责人,对 Elasticsearch 和 Lucene 源码比较熟悉,目前主要负责公司的 Easysearch 产品的研发以及客户服务工作。
> 原文:https://infinilabs.cn/blog/202 ... tion/
Easysearch Java SDK 2.0.x 使用指南(一)
INFINI Labs 小助手 发表了文章 • 0 个评论 • 2949 次浏览 • 2024-12-14 17:50

各位 [Easysearch](https://infinilabs.cn/docs/latest/easysearch/) 的小伙伴们,我们前一阵刚把 easysearch-client 更新到了 2.0.2 版本!借此详细介绍下新版客户端的使用。
新版客户端和 1.0 版本相比,完全重构,抛弃了旧版客户端的一些历史包袱,从里到外都焕然一新!不管是刚入门的小白还是经验丰富的老司机,2.0.x 客户端都能让你开发效率蹭蹭往上涨!
到底有啥新东西?
- 更轻更快: 以前的版本依赖了一堆乱七八糟的东西,现在好了,我们把那些没用的都砍掉了,客户端变得更苗条,性能也杠杠的!
- 类型安全,告别迷糊: 常用的 Easysearch API 现在都配上了强类型的请求和响应对象,再也不用担心写错参数类型了,代码也更好看了,维护起来也更省心!
- 同步异步,想咋用咋用: 所有 API 都支持同步和异步两种调用方式,不管是啥场景,都能轻松应对!
- 构建查询,跟搭积木一样简单: 我们用了流式构建器和函数式编程,构建复杂查询的时候,代码写起来那叫一个流畅,看着也舒服!
- 和 Jackson 无缝对接: 可以轻松地把你的 Java 类和客户端 API 关联起来,数据转换嗖嗖的快!
快速上手
废话不多说,咱们直接上干货!这部分教你怎么快速安装和使用 easysearch-client 2.0.2 客户端,还会演示一些基本操作。
安装
easysearch-client 2.0.2 已经上传到 Maven 中央仓库了,加到你的项目里超级方便。
最低要求: JDK 8 或者更高版本
依赖管理: 客户端内部用 Jackson 来处理对象映射。
Maven 项目
在你的pom.xml
文件的<dependencies>
里面加上这段:
```xml
com.infinilabs
easysearch-client
2.0.2
```
#### Gradle 项目
在你的 `build.gradle` 文件的 `dependencies` 里面加上这段:
```gradle
dependencies {
implementation 'com.infinilabs:easysearch-client:2.0.2'
}
```
### 初始化客户端
下面这段代码演示了怎么初始化一个启用了安全通信加密和 security 的 Easysearch 客户端,看起来有点长,别慌,我们一步一步解释!
```java
public static EasysearchClient create() throws NoSuchAlgorithmException, KeyStoreException,
KeyManagementException {
final HttpHost[] hosts = new HttpHost[]{new HttpHost("localhost", 9200, "https")};
final SSLContext sslContext = SSLContextBuilder.create()
.loadTrustMaterial(null, (chains, authType) -> true).build();
SSLIOSessionStrategy sessionStrategy = new SSLIOSessionStrategy(sslContext, NoopHostnameVerifier.INSTANCE);
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("username", "passwowd"));
RestClient restClient = RestClient.builder(hosts)
.setHttpClientConfigCallback(httpClientBuilder ->
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider)
.setSSLStrategy(sessionStrategy)
.disableAuthCaching()
).setRequestConfigCallback(requestConfigCallback ->
requestConfigCallback.setConnectTimeout(30000).setSocketTimeout(300000))
.build();
EasysearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
return new EasysearchClient(transport);
}
```
这段代码,简单来说,就是:
1. **连上 Easysearch:** 我们要用 HTTPS 连接到本地的 9200 端口。
2. **搞定证书:** 这里为了方便,我们信任了所有证书(注意!生产环境一定要配置好你们自己的证书)。
3. **填上用户名密码:** 这里需要填上你的用户名和密码。
4. **设置连接参数:** 设置了连接超时时间(30 秒)和读取超时时间(300 秒)。
5. **创建客户端:** 最后,我们就创建好了一个 `EasysearchClient` 实例,可以开始干活了!
### 举个栗子:批量操作
下面的例子演示了怎么用 `bulk` API 来批量索引数据:
```java
public static void bulk() throws Exception {
String json2 = "{"
+ " \"@timestamp\": \"2023-01-08T22:50:13.059Z\","
+ " \"agent\": {"
+ " \"version\": \"7.3.2\","
+ " \"type\": \"filebeat\","
+ " \"ephemeral_id\": \"3ff1f2c8-1f7f-48c2-b560-4272591b8578\","
+ " \"hostname\": \"ba-0226-msa-fbl-747db69c8d-ngff6\""
+ " }"
+ "}";
EasysearchClient client = create();
BulkRequest.Builder br = new BulkRequest.Builder();
br.index("test1");
for (int i = 0; i < 10; i++) {
BulkOperation.Builder builder = new BulkOperation.Builder();
IndexOperation.Builder indexBuilder = new IndexOperation.Builder();
builder.index(indexBuilder.document(JsonData.fromJson(json2)).build());
br.operations(builder.build());
}
for (int i = 0; i < 10; i++) {
BulkOperation.Builder builder = new BulkOperation.Builder();
IndexOperation.Builder indexBuilder = new IndexOperation.Builder();
indexBuilder.document(JsonData.fromJson(json2)).index("test2");
builder.index(indexBuilder.build());
br.operations(builder.build());
}
for (int i = 0; i < 10; i++) {
Mapmap = new HashMap<>();
map.put("@timestamp", "2023-01-08T22:50:13.059Z");
map.put("field1", "value1");
IndexOperation.Builder indexBuilder = new IndexOperation.Builder();
indexBuilder.document(map).index("test3");
br.operations(new BulkOperation(indexBuilder.build()));
}
BulkResponse bulkResponse = client.bulk(br.build());
if (bulkResponse.errors()) {
for (BulkResponseItem item : bulkResponse.items()) {
System.out.println(item.toString());
}
}
client._transport().close();
}
```
这个例子里,我们一口气把数据批量索引到了 `test1`、`test2` 和 `test3` 这三个索引里,
并且展示了三种在 bulk API 中构建 IndexOperation 的方式,虽然它们最终都能实现将文档索引到 Easysearch,但在使用场景和灵活性上还是有一些区别的:
这段代码的核心是利用 BulkRequest.Builder 来构建一个批量请求,并通过 br.operations(...) 方法添加多个操作。而每个操作,在这个例子里,都是一个 IndexOperation,也就是索引一个文档。IndexOperation 可以通过 IndexOperation.Builder 来创建。
三种方式的区别主要体现在如何构建 IndexOperation 里的 document 部分,也就是要索引的文档内容。
**第一种方式:使用 JsonData.fromJson(json2) 且不指定索引。**
特点:
使用 JsonData.fromJson(json2) 将一个 JSON 字符串直接转换成 JsonData 对象作为文档内容。
这里没有在 IndexOperation.Builder 上调用 index() 方法来指定索引名称。由于没有在每个 IndexOperation 中指定索引,这个索引名称将回退到 BulkRequest.Builder 上设置的索引,即 br.index("test1"),所以这 10 个文档都会被索引到 test1。
当你需要将一批相同结构的 JSON 文档索引到同一个索引时,这种方式比较简洁。
**第二种方式:使用 JsonData.fromJson(json2) 并指定索引**
特点:
同样使用 JsonData.fromJson(json2) 将 JSON 字符串转换成 JsonData 对象。
关键区别在于,这里在 IndexOperation.Builder 上调用了 index("test2"),为每个操作单独指定了索引名称。
这 10 个文档会被索引到 test2,即使 BulkRequest.Builder 上设置了 index("test1") 也没用,因为 IndexOperation 里的设置优先级更高。
当你需要将一批相同结构的 JSON 文档索引到不同的索引时,就需要使用这种方式来分别指定索引。
**第三种方式:使用 Map并指定索引**
特点:
使用 Map来构建文档内容,这种方式更加灵活,可以构建任意结构的文档。
同样在 IndexOperation.Builder 上调用了 index("test3") 指定了索引名称。
使用 new BulkOperation(indexBuilder.build()) 代替之前的 builder.index(indexBuilder.build()), 这是等价的。
这 10 个文档会被索引到 test3。
当你需要索引的文档结构不固定,或者你需要动态构建文档内容时,使用 Map 是最佳选择。例如,你可以根据不同的业务逻辑,往 Map 里添加不同的字段。
## 总结
这次 easysearch-client 2.0.x Java 客户端的更新真的很给力,强烈建议大家升级体验!相信我,用了新版客户端,你的开发效率绝对会提升一大截!
---
**想要了解更多?**
- 客户端 Maven 地址: [https://mvnrepository.com/arti ... 2.0.2](https://mvnrepository.com/arti ... /2.0.2)
- 更详细的文档和示例代码在 [官网](https://infinilabs.cn/docs/lat ... t-api/) 持续更新中,请随时关注!
大家有啥问题或者建议,也欢迎随时反馈!
作者:张磊,极限科技(INFINI Labs)搜索引擎研发负责人,对 Elasticsearch 和 Lucene 源码比较熟悉,目前主要负责公司的 Easysearch 产品的研发以及客户服务工作。
【第3期】INFINI Easysearch 免费认证培训开放报名
INFINI Labs 小助手 发表了文章 • 0 个评论 • 6079 次浏览 • 2024-09-13 17:43
探索 Easysearch 的无限可能,与 INFINI Labs 共赴搜索技术前沿!
随着数字化转型的加速,搜索技术已成为企业数据洞察的核心。INFINI Labs 作为搜索创新技术的引领者,诚邀所有对 Easysearch 搜索引擎感兴趣的开发者、技术爱好者及合作伙伴,参加我们即将于 2024 年 10 月 19 日至 20 日举办的第 3 期 Easysearch 线上免费培训活动。这不仅是一场知识的盛宴,更是技能提升的加速器,将助您在职业道路上迈出坚实的一步!
活动亮点
- 系统课程,全面深入:从 Easysearch 的基本概念到环境搭建,再到高级功能的实战应用,INFINI Labs 的技术专家将为您带来全面而深入的讲解,确保每位参与者都能收获满满。
- 实战导向,解决痛点:课程设计紧贴实际需求,旨在帮助学员掌握 Easysearch 的核心技术,有效解决工作中的搜索需求和技术难题,让理论知识迅速转化为实践能力。
- 认证证书,助力进阶:后期 INFINI Labs 将推出 Easysearch 认证考试。通过考试的学员将获得官方认证的 Easysearch 证书,为您的职业发展增添强力背书,开启职业生涯的新篇章。
培训时间
2024 年 10 月 19 日至 20 日(周六、周日)共两天,每天具体培训时间:
- 上午 09:30 ~ 11:30
- 下午 14:00 ~ 16:00
培训内容概览
第一阶段:初识 Easysearch
- Easysearch 环境搭建与对比,了解其与 Elasticsearch 的差异;
- 功能初探:身份验证、数据脱敏、权限控制等,全面掌握 Easysearch 的基础功能;
- 容灾技术:兼容性验证、跨集群复制等,确保您的搜索服务稳定可靠;
第二阶段:Easysearch 高阶使用
- 深度探析:性能压测、数据迁移、请求管理等,提升 Easysearch 的使用效率;
- 高级功能:快照管理、可视化看板、告警功能等,让您的搜索服务更加智能;
- 生态集成:Filebeat、Logstash、LangChain 等,轻松实现 Easysearch 与其他工具的集成;
参与方式
本次活动完全免费,名额有限,请尽快报名,同时微信扫码添加小助手进群(培训会议地址将在微信群公布),锁定您的学习席位!
扫码或点击 [我要报名](https://hdxu.cn/Qo9UJ)

👉 立即行动:不要错过这次提升自我、与行业精英共成长的宝贵机会。让我们相聚云端,共同探索 Easysearch 的无限可能,开启技术进阶的新篇章!
参会提示
- 培训内容涉及动手实践,请务必自备电脑(Windows 系统环境请提前安装好 Linux 虚拟机);
- 请提前在 INFINI Labs 官网下载对应平台最新安装包(INFINI Easysearch、INFINI Gateway、INFINI Console);
- 下载地址:[https://infinilabs.cn/download](https://infinilabs.cn/download)
联系我们
如有任何疑问,欢迎通过微信添加 [小助手:INFINI-Labs] 与我们联系。
INFINI Labs 期待与您相约,共赴这场技术盛宴!
关于 Easysearch

Easysearch 是一个分布式的近实时搜索与分析引擎,基于开源的 Apache Lucene 构建。它旨在提供一个自主可控、轻量级的 Elasticsearch 可替代版本,并不断完善和支持更多的企业级功能。与 Elasticsearch 相比,Easysearch 更注重搜索业务场景的优化,同时保持其产品的简洁与易用性。
详情参见:[Easysearch 介绍](https://infinilabs.cn/products/easysearch)
关于极限科技(INFINI Labs)

极限科技,全称极限数据(北京)科技有限公司,是一家专注于实时搜索与数据分析的软件公司。旗下品牌极限实验室(INFINI Labs)致力于打造极致易用的数据探索与分析体验。
极限科技是一支年轻的团队,采用天然分布式的方式来进行远程协作,员工分布在全球各地,希望通过努力成为中国乃至全球企业大数据实时搜索分析产品的首选,为中国技术品牌输出添砖加瓦。
官网:[https://infinilabs.cn](https://infinilabs.cn)
如何用 Scrapy 爬取网站数据并在 Easysearch 中进行存储检索分析
INFINI Labs 小助手 发表了文章 • 0 个评论 • 6177 次浏览 • 2024-09-13 12:28

做过数据分析和爬虫程序的小伙伴想必对 Scrapy 这个爬虫框架已经很熟悉了。今天给大家介绍下,如何基于 Scrapy 快速编写一个爬虫程序并利用 Easysearch 储存、检索、分析爬取的数据。我们以极限科技的官网 Blog 为数据源([https://infinilabs.cn/blog](https://infinilabs.cn/blog)) ,做下实操演示。
1、安装 scrapy
使用 Scrapy 可以快速构建一个爬虫项目,从目标网站中获取所需的数据,并进行后续的处理和分析。
```python
pip install scrapy
新建项目 infini_spiders
scrapy startproject infini_spiders
初始化爬虫
cd infini_spiders/spiders
scrapy genspider blog infinilabs.cn
```
2、爬虫编写
编写一个爬虫文件 blog.py ,它会首先访问 start_urls 指定的地址,将结果发给 parse 函数解析。通过这一步解析,我们得到了每一篇博客的地址。然后我们对每个博客的地址发送请求,将结果发给 parse_blog 函数进行解析,在这里才会真正提取每篇博客的 title、tag、url、date、content 内容。
python<br /> from typing import Any, Iterable<br /> import scrapy<br /> from bs4 import BeautifulSoup<br /> from scrapy.http import Response<br /> <br /> class BlogSpider(scrapy.Spider):<br /> name = "blog"<br /> allowed_domains = ["infinilabs.cn"]<br /> start_urls = ["<a href="https://infinilabs.cn/blog/"" rel="nofollow" target="_blank">https://infinilabs.cn/blog/"</a>]<br /> <br /> def parse(self, response):<br /> links = response.css("div.blogs a")<br /> yield from response.follow_all(links, self.parse_blog)<br /> <br /> def parse_blog(self, response):<br /> title = response.xpath('//div[@class="title"]/text()').extract_first()<br /> tags = response.xpath('//div[@class="tags"]/div[@class="tag"]/text()').extract()<br /> url = response.url<br /> author = response.xpath('//div[@class="logo"]/div[@class="name"]//text()').extract_first()<br /> date = response.xpath('//div[@class="date"]/text()').extract_first()<br /> all_text = response.xpath('//p//text() | //h3/text() | //h2/text() | //h4/text() | //ol/li//text()').extract()<br /> content = '\n'.join(all_text)<br /> <br /> yield {<br /> 'title': title,<br /> 'tags': tags,<br /> 'url': url,<br /> 'author': author,<br /> 'date': date,<br /> 'content': content<br /> }<br />
提取完我们想要的内容后,接下来就要考虑存储了。考虑到要对内容进行检索、分析,接下来我们将内容直接存放到 Easysearch 当中。
3、安装插件
通过安装 ScrapyElasticsearch pipeline 可将 scrapy 爬取的内容存入到 Easysearch 中。
python<br /> pip install ScrapyElasticSearch<br />
修改 scrapy 自带的配置文件 settings.py ,添加以下内容。
python<br /> ITEM_PIPELINES = {<br /> 'scrapyelasticsearch.scrapyelasticsearch.ElasticSearchPipeline': 10<br /> }<br /> <br /> ELASTICSEARCH_SERVERS = ['http://192.168.56.3:9210']<br /> ELASTICSEARCH_INDEX = 'scrapy'<br /> ELASTICSEARCH_INDEX_DATE_FORMAT = '%Y-%m-%d'<br /> ELASTICSEARCH_TYPE = '_doc'<br /> ELASTICSEARCH_USERNAME = 'admin'<br /> ELASTICSEARCH_PASSWORD = '9423d1d5345ed6d0db19'<br />
ScrapyElasticSearch 会以 bulk 方式写入 Easysearch,每次批量的大小由 scrapyelasticsearch.scrapyelasticsearch.ElasticSearchPipeline 参数控制,大家可自行修改。
在上述配置中,我们会将爬到的数据存放到 scrapy-yyyy-mm-dd 索引中。
4、启动爬虫
在 infini_spiders/spiders 目录下,使用命令启动爬虫。
bash<br /> scrapy crawl blog<br />
blog 就是爬虫的名字,对应到 blog.py 里面的 name 变量。运行完成后,就可以去 Easysearch 里查看数据了,当然我们还是使用 Console 进行查看。
5、查看数据
先查看下索引情况,scrapy 索引已经生成,里面有 129 篇博客。

查看详细内容,确保博客正文已经保存。

到了这一步,我们就能使用 [Console](https://infinilabs.cn/products/console) 对博客进行搜索、分析了。


6、结语
这次的分享就到这里了。欢迎与我一起交流 ES 的各种问题和解决方案。

关于 Easysearch

INFINI Easysearch 是一个分布式的近实时搜索与分析引擎,核心引擎基于开源的 Apache Lucene。Easysearch 的目标是提供一个轻量级的 Elasticsearch 可替代版本,并继续完善和支持更多的企业级功能。 与 Elasticsearch 相比,Easysearch 更关注在搜索业务场景的优化和继续保持其产品的简洁与易用性。
官网文档:<https://infinilabs.cn/docs/latest/easysearch>
作者:杨帆
原文:https://infinilabs.cn/blog/202 ... arch/
Easysearch 性能测试方法概要
INFINI Labs 小助手 发表了文章 • 0 个评论 • 3616 次浏览 • 2024-08-23 14:47
INFINI Easysearch
INFINI Easysearch 是一个分布式的近实时搜索与分析引擎,核心引擎基于开源的 Apache Lucene。Easysearch 衍生自基于开源协议 Apache 2.0 的 Elasticsearch 7.10 版本,完善和支持更多的企业级功能,优化搜索业务场景,以保证更佳的数据探索与分析体验。
Easysearch 的主要特点:
- 兼容 Elasticsearch,业务代码无需改动;可平滑迁移
- 企业级安全;更稳定可靠
- 企业级管理后台(多集群统一管理,实现运营标准化、自动化)
- 信创适配(全面适配国产 CPU/OS/服务器,支持国密算法)
Easysearch 快速体验,请参阅:
[Easysearch,地表最强,没有之一!](https://mp.weixin.qq.com/s/6kLF713Tu2fmSV3JWu12kg)
Loadgen
Loadgen 是 Elasticsearch 专属压测工具,用来对 Easysearch 或者网关进行压力测试。
Loadgen 的特点:
- 性能强劲
- 轻量级无依赖
- 支持模板化参数随机
- 支持高并发
- 支持压测端均衡流量控制
- 支持服务端返回值校验
当前最新版本为 1.26.1-598,下载链接如下:
[https://release.infinilabs.com/loadgen/stable/](https://release.infinilabs.com/loadgen/stable/)
下载并解压安装包后,得到二进制文件。
查看版本信息。
sh<br /> $ ./loadgen-linux-amd64 -v<br /> __ ___ _ ___ ___ __ __<br /> / / /___\/_\ / \/ _ \ /__\/\ \ \<br /> / / // ///_\\ / /\ / /_\//_\ / \/ /<br /> / /__/ \_// _ \/ /_// /_\\//__/ /\ /<br /> \____|___/\_/ \_/___,'\____/\__/\_\ \/<br /> <br /> [LOADGEN] A http load generator and testing suite.<br /> [LOADGEN] 1.26.1#598, 2024-08-14 04:50:03, 2024-12-31 10:10:10, 00f15fd86834d7ea539f6d66ee608e3915eef0e3<br /> loadgen 1.26.1 598 2024-08-14 04:50:03 +0000 UTC 2024-12-31 10:10:10 +0000 UTC 00f15fd86834d7ea539f6d66ee608e3915eef0e3<br />
Loadgen 测试
Loadgen 使用非常简单,下面演示如何进行查询压测。
- 建立索引,根据节点数调节分片数。
sh<br /> curl -X PUT -H "Content-Type: application/json" \<br /> -ku admin:xxx "<a href="https://localhost:9200/loadtest"" rel="nofollow" target="_blank">https://localhost:9200/loadtest"</a> -d'<br /> {<br /> "settings":{<br /> "number_of_shards":"3",<br /> "number_of_replicas":1,<br /> "translog":{<br /> "durability":"async"<br /> }<br /> }<br /> }'<br /> {"acknowledged":true,"shards_acknowledged":true,"index":"loadtest"}<br />
- 创建
loadgen.dsl.shawnyan
配置文件,定义查询
sh<br /> GET loadtest/_search<br /> {"query": {"term": {"id.keyword": {"value": $[[id]]}}}}<br />
- 执行压测,
-d
表示秒数,-c
表示并发数。
sh<br /> $ ES_ENDPOINT=https://localhost:9200 ES_USERNAME=admin ES_PASSWORD=xxx ./loadgen-linux-amd64 -run loadgen.dsl.shawnyan -d 10 -c 2<br /> __ ___ _ ___ ___ __ __<br /> / / /___\/_\ / \/ _ \ /__\/\ \ \<br /> / / // ///_\\ / /\ / /_\//_\ / \/ /<br /> / /__/ \_// _ \/ /_// /_\\//__/ /\ /<br /> \____|___/\_/ \_/___,'\____/\__/\_\ \/<br /> <br /> [LOADGEN] A http load generator and testing suite.<br /> [LOADGEN] 1.26.1#598, 2024-08-14 04:50:03, 2024-12-31 10:10:10, 00f15fd86834d7ea539f6d66ee608e3915eef0e3<br /> [08-19 16:43:27] [INF] [env.go:179] configuration auto reload enabled<br /> [08-19 16:43:27] [INF] [app.go:285] initializing loadgen, pid: 30792<br /> [08-19 16:43:27] [INF] [app.go:286] using config: /data/es/loadgen.yml<br /> [08-19 16:43:27] [INF] [module.go:155] started plugin: statsd<br /> [08-19 16:43:27] [INF] [module.go:161] all modules are started<br /> [08-19 16:43:27] [INF] [instance.go:78] workspace: /data/es/data/loadgen/nodes/cr1gabqr90cng685o2s0<br /> [08-19 16:43:27] [INF] [app.go:511] loadgen is up and running now.<br /> [08-19 16:43:27] [INF] [main.go:403] loading config: /data/es/loadgen.dsl.shawnyan<br /> <br /> 21108 requests finished in 9.79061677s, 1.08MB sent, 3.22MB received<br /> <br /> [Loadgen Client Metrics]<br /> Requests/sec: 2110.63<br /> Request Traffic/sec: 110.22KB<br /> Total Transfer/sec: 440.00KB<br /> Fastest Request: 680.198µs<br /> Slowest Request: 12.409574ms<br /> Status 200: 21108<br /> <br /> [Latency Metrics]<br /> 10000 samples of 21108 events<br /> Cumulative: 8.732205871s<br /> HMean: 851.869µs<br /> Avg.: 873.22µs<br /> p50: 839.498µs<br /> p75: 914.298µs<br /> p95: 1.059197ms<br /> p99: 1.327098ms<br /> p999: 4.83579ms<br /> Long 5%: 1.394411ms<br /> Short 5%: 724.226µs<br /> Max: 11.618475ms<br /> Min: 680.198µs<br /> Range: 10.938277ms<br /> StdDev: 289.216µs<br /> Rate/sec.: 2110.63<br /> <br /> [Latency Distribution]<br /> 680µs - 1.774ms ------------------------------<br /> 1.774ms - 2.867ms -<br /> 2.867ms - 3.961ms -<br /> 3.961ms - 5.055ms -<br /> 5.055ms - 6.149ms -<br /> 6.149ms - 7.243ms -<br /> 7.243ms - 8.336ms -<br /> 8.336ms - 9.43ms -<br /> 9.43ms - 10.524ms -<br /> 10.524ms - 11.618ms -<br /> <br /> <br /> [Estimated Server Metrics]<br /> Requests/sec: 2155.94<br /> Avg Req Time: 927.668µs<br /> Transfer/sec: 449.45KB<br />
更多内容请参阅文档:
[https://infinilabs.cn/docs/lat ... mark/](https://infinilabs.cn/docs/lat ... hmark/)
Rally
如果对 Elasticsearch 熟悉的同学,也可尝试使用 Rally 对 Easysearch 进行测试。
Rally 是 Elasticsearch 的基准测试框架。它可以帮助您完成以下任务:
- 建立索引,根据节点数调节分片数。
- 安装 Elasticsearch 集群以进行基准测试
- 跨 Elasticsearch 版本管理基准数据和规范
- 运行基准测试并记录结果
- 通过连接遥测设备来查找性能问题
- 比较性能结果
安装 Rally。
sh<br /> [root@easysearch /]# pip3 install esrally<br /> Requirement already satisfied: esrally in /usr/local/lib/python3.9/site-packages (2.11.0)<br /> Requirement already satisfied: py-cpuinfo==7.0.0 in /usr/local/lib/python3.9/site-packages (from esrally) (7.0.0)<br /> Requirement already satisfied: elastic-transport==8.4.1 in /usr/local/lib/python3.9/site-packages (from esrally) (8.4.1)<br /> Requirement already satisfied: google-resumable-media[requests]==1.1.0 in /usr/local/lib/python3.9/site-packages (from esrally) (1.1.0)<br /> Requirement already satisfied: urllib3==1.26.18 in /usr/local/lib/python3.9/site-packages (from esrally) (1.26.18)<br /> Requirement already satisfied: google-auth==1.22.1 in /usr/local/lib/python3.9/site-packages (from esrally) (1.22.1)<br /> Requirement already satisfied: thespian==3.10.1 in /usr/local/lib/python3.9/site-packages (from esrally) (3.10.1)<br /> Requirement already satisfied: jsonschema==3.1.1 in /usr/local/lib/python3.9/site-packages (from esrally) (3.1.1)<br /> Requirement already satisfied: markupsafe==2.0.1 in /usr/local/lib64/python3.9/site-packages (from esrally) (2.0.1)<br /> Requirement already satisfied: yappi==1.5.1 in /usr/local/lib64/python3.9/site-packages (from esrally) (1.5.1)<br /> Requirement already satisfied: psutil==5.9.4 in /usr/local/lib64/python3.9/site-packages (from esrally) (5.9.4)<br /> Requirement already satisfied: certifi in /usr/local/lib/python3.9/site-packages (from esrally) (2024.7.4)<br /> Requirement already satisfied: elasticsearch[async]==8.6.1 in /usr/local/lib/python3.9/site-packages (from esrally) (8.6.1)<br /> Requirement already satisfied: ijson==2.6.1 in /usr/local/lib/python3.9/site-packages (from esrally) (2.6.1)<br /> Requirement already satisfied: jinja2==3.1.4 in /usr/local/lib/python3.9/site-packages (from esrally) (3.1.4)<br /> Requirement already satisfied: requests<2.32.0 in /usr/local/lib/python3.9/site-packages (from esrally) (2.31.0)<br /> Requirement already satisfied: tabulate==0.8.9 in /usr/local/lib/python3.9/site-packages (from esrally) (0.8.9)<br /> Requirement already satisfied: zstandard==0.21.0 in /usr/local/lib64/python3.9/site-packages (from esrally) (0.21.0)<br /> Requirement already satisfied: docker==6.0.0 in /usr/local/lib/python3.9/site-packages (from esrally) (6.0.0)<br /> Requirement already satisfied: websocket-client>=0.32.0 in /usr/local/lib/python3.9/site-packages (from docker==6.0.0->esrally) (1.8.0)<br /> Requirement already satisfied: packaging>=14.0 in /usr/lib/python3.9/site-packages (from docker==6.0.0->esrally) (20.9)<br /> Requirement already satisfied: aiohttp<4,>=3 in /usr/local/lib64/python3.9/site-packages (from elasticsearch[async]==8.6.1->esrally) (3.10.4)<br /> Requirement already satisfied: pyasn1-modules>=0.2.1 in /usr/local/lib/python3.9/site-packages (from google-auth==1.22.1->esrally) (0.4.0)<br /> Requirement already satisfied: six>=1.9.0 in /usr/lib/python3.9/site-packages (from google-auth==1.22.1->esrally) (1.15.0)<br /> Requirement already satisfied: rsa<5,>=3.1.4 in /usr/local/lib/python3.9/site-packages (from google-auth==1.22.1->esrally) (4.9)<br /> Requirement already satisfied: setuptools>=40.3.0 in /usr/lib/python3.9/site-packages (from google-auth==1.22.1->esrally) (53.0.0)<br /> Requirement already satisfied: cachetools<5.0,>=2.0.0 in /usr/local/lib/python3.9/site-packages (from google-auth==1.22.1->esrally) (4.2.4)<br /> Requirement already satisfied: google-crc32c<2.0dev,>=1.0 in /usr/local/lib64/python3.9/site-packages (from google-resumable-media[requests]==1.1.0->esrally) (1.5.0)<br /> Requirement already satisfied: attrs>=17.4.0 in /usr/local/lib/python3.9/site-packages (from jsonschema==3.1.1->esrally) (24.2.0)<br /> Requirement already satisfied: importlib-metadata in /usr/local/lib/python3.9/site-packages (from jsonschema==3.1.1->esrally) (8.2.0)<br /> Requirement already satisfied: pyrsistent>=0.14.0 in /usr/local/lib64/python3.9/site-packages (from jsonschema==3.1.1->esrally) (0.20.0)<br /> Requirement already satisfied: yarl<2.0,>=1.0 in /usr/local/lib64/python3.9/site-packages (from aiohttp<4,>=3->elasticsearch[async]==8.6.1->esrally) (1.9.4)<br /> Requirement already satisfied: frozenlist>=1.1.1 in /usr/local/lib64/python3.9/site-packages (from aiohttp<4,>=3->elasticsearch[async]==8.6.1->esrally) (1.4.1)<br /> Requirement already satisfied: aiosignal>=1.1.2 in /usr/local/lib/python3.9/site-packages (from aiohttp<4,>=3->elasticsearch[async]==8.6.1->esrally) (1.3.1)<br /> Requirement already satisfied: async-timeout<5.0,>=4.0 in /usr/local/lib/python3.9/site-packages (from aiohttp<4,>=3->elasticsearch[async]==8.6.1->esrally) (4.0.3)<br /> Requirement already satisfied: aiohappyeyeballs>=2.3.0 in /usr/local/lib/python3.9/site-packages (from aiohttp<4,>=3->elasticsearch[async]==8.6.1->esrally) (2.3.7)<br /> Requirement already satisfied: multidict<7.0,>=4.5 in /usr/local/lib64/python3.9/site-packages (from aiohttp<4,>=3->elasticsearch[async]==8.6.1->esrally) (6.0.5)<br /> Requirement already satisfied: pyparsing>=2.0.2 in /usr/lib/python3.9/site-packages (from packaging>=14.0->docker==6.0.0->esrally) (2.4.7)<br /> Requirement already satisfied: pyasn1<0.7.0,>=0.4.6 in /usr/local/lib/python3.9/site-packages (from pyasn1-modules>=0.2.1->google-auth==1.22.1->esrally) (0.6.0)<br /> Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.9/site-packages (from requests<2.32.0->esrally) (3.7)<br /> Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib64/python3.9/site-packages (from requests<2.32.0->esrally) (3.3.2)<br /> Requirement already satisfied: zipp>=0.5 in /usr/local/lib/python3.9/site-packages (from importlib-metadata->jsonschema==3.1.1->esrally) (3.20.0)<br /> WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: <a href="https://pip.pypa.io/warnings/venv" rel="nofollow" target="_blank">https://pip.pypa.io/warnings/venv</a><br /> [root@easysearch /]# esrally --version<br /> esrally 2.11.0<br /> [root@easysearch /]#<br />
关于 Rally 的更多内容,请参阅官方文档:
[https://esrally.readthedocs.io/en/stable/](https://esrally.readthedocs.io/en/stable/)
作者:少安事务所
原文:https://mp.weixin.qq.com/s/9eEH38kgsw4i150CJqyxvQ
Easysearch x 《黑神话悟空》有奖征文获奖结果公示
INFINI Labs 小助手 发表了文章 • 0 个评论 • 3238 次浏览 • 2024-08-20 13:34
随着《黑神话:悟空》游戏的正式发售,我们 INFINI Labs 组织的 Easysearch 有奖征文大赛也圆满落幕。本次征文活动自启动以来,收到了众多创作者的热情投稿。在此,我们衷心感谢每一位参与活动的作者,是你们的才华和热情让这次征文活动异彩纷呈。
经过专业评审团的认真评选,最终确定了以下获奖作品及作者,现予以公布:
| 奖项 | 作者 | 作品 | 奖品 |
| ------ | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------- |
| 一等奖 | AWS 加油站 | [玩转 Easysearch 语法](https://blog.csdn.net/weixin_3 ... 227001) | 《黑神话:悟空》数字豪华版一套 |
| 二等奖 | 杨帆 | [使用 Easysearch 打造企业内部知识问答系统](https://infinilabs.cn/blog/202 ... earch/) | 《黑神话:悟空》数字标准版一套 |
| 二等奖 | 李家兴 | [从 Elasticsearch 到 Easysearch:国产搜索型数据库的崛起与未来展望](https://infinilabs.cn/blog/202 ... bases/) | 《黑神话:悟空》数字标准版一套 |
| 三等奖 | 严少安 | [Easysearch,地表最强,没有之一!](https://www.modb.pro/db/1823222832453660672) | INFINI Labs 咖啡杯 / 指甲剪套装 |
| 三等奖 | 张磊 | [Easysearch 新特性:写入限流功能介绍](https://infinilabs.cn/blog/202 ... ction/) | INFINI Labs 咖啡杯 / 指甲剪套装 |
| 三等奖 | keep | [如何在 MacOS 环境下快速安装部署 Easysearch](https://blog.csdn.net/weixin_4 ... 238374) | INFINI Labs 咖啡杯 / 指甲剪套装 |
恭喜以上获奖作者,你们的作品不仅展现了 Easysearch 的强大功能,也为社区成员提供了宝贵的学习资源。我们将会通过小助手微信联系各位获奖者,安排奖品的发放。
同时,我们也要感谢所有参与本次征文活动的作者,你们的每一篇 Easysearch 投稿都是对社区的一份贡献。我们期待在未来的活动中再次与大家相遇。
请继续关注 INFINI Labs,我们将持续为大家带来更多优质的产品和精彩的活动。再次感谢大家的参与和支持!
如有疑问或想加入 Easysearch 用户交流群请联系我们小助手!

附征文活动原文:
[天命人, 你在吗?快拿走你的《黑神话:悟空》游戏,去开启神话冒险!](https://infinilabs.cn/blog/202 ... ukong/)
关于极限科技(INFINI Labs)

极限科技,全称极限数据(北京)科技有限公司,是一家专注于实时搜索与数据分析的软件公司。旗下品牌极限实验室(INFINI Labs)致力于打造极致易用的数据探索与分析体验。
极限科技是一支年轻的团队,采用天然分布式的方式来进行远程协作,员工分布在全球各地,希望通过努力成为中国乃至全球企业大数据实时搜索分析产品的首选,为中国技术品牌输出添砖加瓦。
官网:[https://infinilabs.cn](https://infinilabs.cn)
如何在 MacOS 环境下快速安装部署 Easysearch
INFINI Labs 小助手 发表了文章 • 0 个评论 • 3275 次浏览 • 2024-08-17 14:56
1、什么是 Easysearch

Easysearch 是极限科技研发的一个分布式的近实时搜索与分析引擎,核心引擎基于开源的 Apache Lucene。 同时也是一款具备自主可控的分布式近实时搜索型数据库产品,具备高性能、高可用、弹性伸缩、高安全性等特性,具备支持丰富的个性化搜索及聚合分析能力,可部署在物理机、虚拟机、容器、私有云和公有云,能承载 PB 级别的海量业务数据,为金融核心系统、运营商、制造业和政企业务系统提供安全、稳定、可靠的快速检索和实时数据探索分析能力,可满足不同业务场景的各项复杂需求。
2、前期准备
在安装 Easysearch 之前,确保您的 MacOS 系统符合以下要求:
- MacOS 操作系统版本应为最新或推荐稳定版本。
- 确保系统上已安装 Java 运行环境,因为 Easysearch 是基于 Java 开发的。
3、下载 Easysearch
打开浏览器,访问 [Easysearch 官方下载页面](https://infinilabs.cn/download/?product=easysearch)。
找到 MacOS 版本安装包,然后根据自己电脑 CPU 架构选择对应的 Easysearch 安装包。我自己的电脑是 Intel X86 架构,直接选择默认的 amd64,点击下载即可。如果你的电脑是 Apple 的自己的 M 系列芯片,请选择 arm64 版本安装包。
4、安装 Easysearch
打开终端(Terminal)并导航到下载目录,找到 Easysearch 的压缩包,然后双击解压到您选择的目录。或者使用以下命令解压文件:
bash<br /> unzip ./easysearch-1.8.3-265-mac-amd64.zip<br />
5、启动 Easysearch
- 执行初始化脚本:
由于 Easysearch 默认自带了安全模块,所以在启动之前需要先执行初始化脚本,脚本里会自动帮我们处理好 Easysearch 安全证书、下载基本的 plugins 插件以及初始用户名和密码等,方便省心。
bash<br /> cd ./easysearch-1.8.3-265-mac-amd64 && bin/initialize.sh<br />
执行过程中遇到 [y/N] 询问,输入 y 即可。最后执行完初始化脚本之后,我们可以在输出的 log 日志中看到 easysearch 的访问用户名和密码,需要注意的是,这个用户名和密码需要自己保存好。 如下图所示:
- 启动 Easysearch:
使用以下命令启动 Easysearch:
bash<br /> ./bin/easysearch<br />
启动后,Easysearch 将在终端中输出运行日志,您可以在此查看启动过程中的详细信息。
6、验证安装
- 检查运行状态:
打开浏览器,访问<a href="https://localhost:9200" rel="nofollow" target="_blank">https://localhost:9200</a>
,输入上面提到的用户名密码,如果您看到类似以下的 JSON 响应,说明 Easysearch 已成功启动:
- 检查集群健康状况:
在浏览器中输入https:/localhost:9200/_cluster/health?pretty
或者在终端中执行以下命令来检查集群的健康状况:
bash<br /> curl -ku admin:4395c2f67208ca5ad7de <a href="https://localhost:9200/_cluster/health?pretty"" rel="nofollow" target="_blank">https://localhost:9200/_cluste ... ot%3B</a><br />
这将返回集群的详细健康信息,status
为 green 表示集群状态正常。如下图所示:
7、总结
通过上述步骤,可以轻松地在 MacOS 环境下安装和部署 Easysearch,享受它带来的强大功能和便捷体验。Easysearch 作为 Elasticsearch 的替代产品,不仅在功能上保持了高效和稳定,还进一步优化了搜索业务场景,使其更适合企业级应用。现在,您可以进一步配置集群,开始索引数据,并探索 Easysearch 提供的强大搜索和分析功能。建议参考 [官网文档](https://infinilabs.cn/docs/lat ... rview/),深入了解并实践更多高级功能。
关于 Easysearch 有奖征文活动

无论你是 Easysearch 的老用户,还是第一次听说这个名字,只要你对 INFINI Labs 旗下的 Easysearch 产品感兴趣,或者是希望了解 Easysearch,都可以参加这次活动。
详情查看:[Easysearch 征文活动](https://infinilabs.cn/blog/202 ... ukong/)
作者:Keep simple
原文:https://blog.csdn.net/weixin_4 ... 38374
- 执行初始化脚本:
使用 AWS EKS 部署 Easysearch
INFINI Labs 小助手 发表了文章 • 0 个评论 • 3268 次浏览 • 2024-08-15 15:47
随着企业对数据搜索和分析需求的增加,高效的搜索引擎解决方案变得越来越重要。[Easysearch](https://infinilabs.cn/blog/202 ... yntax/) 作为一款强大的企业级搜索引擎,可以帮助企业快速构建高性能、可扩展的数据检索系统。在云计算的背景下,使用容器化技术来部署和管理这些解决方案已经成为主流选择,而 Amazon Elastic Kubernetes Service (EKS) 则提供了一个强大且易于使用的平台来运行容器化的应用程序。
本文旨在探索如何在 AWS EKS 上部署 Easysearch,并通过实践操作展示从集群配置到服务部署的完整过程。通过本文,读者可以了解如何在云环境中快速搭建高效的搜索服务,最大化利用云资源的弹性和可扩展性。
准备工作
- 准备一个 AWS Global 账户,本文选择东京区域(ap-northeast-1)进行部署。
- 部署 EKS 集群版本为 1.30,同时需要在 Linux 环境中安装 AWS CLI、Helm、eksctl 和 kubectl 等命令行工具。本文使用 eksctl 管理 EKS 集群,eksctl 是 AWS 官方推出的高效管理 EKS 集群的命令行工具。
- 本文将使用 EBS-CSI-Driver 作为存储驱动来部署 Easysearch 服务,并通过 AWS LoadBalancer Controller 将 Easysearch Console 服务以 AWS 负载均衡器的方式对外提供服务,连接集群内部的 Easysearch。
命令行工具的安装
安装 AWS CLI:
shell<br /> curl "<a href="https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip"" rel="nofollow" target="_blank">https://awscli.amazonaws.com/a ... ot%3B</a> -o "awscliv2.zip"<br /> unzip awscliv2.zip<br /> ./aws/install -i /usr/local/aws-cli -b /usr/local/bin<br /> aws --version<br />
安装 Helm:
shell<br /> curl <a href="https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3" rel="nofollow" target="_blank">https://raw.githubusercontent. ... elm-3</a> > get_helm.sh<br /> chmod 700 get_helm.sh<br /> ./get_helm.sh<br />
安装 eksctl:
```shell对于 ARM 系统,设置 ARCH 为:
arm64
、armv6
或armv7
ARCH=amd64
PLATFORM=$(uname -s)$ARCH
curl -sLO "<a href="https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl" rel="nofollow" target="blank">https://github.com/eksctl-io/e ... sctl$PLATFORM.tar.gz"
(可选)验证校验和
curl -sL "<a href="https://github.com/eksctl-io/eksctl/releases/latest/download/eksctl_checksums.txt"" rel="nofollow" target="blank">https://github.com/eksctl-io/e ... ot%3B | grep $PLATFORM | sha256sum --check
tar -xzf eksctl$PLATFORM.tar.gz -C /tmp && rm eksctl_$PLATFORM.tar.gz
sudo mv /tmp/eksctl /usr/local/bin
<br /> <br /> 安装 kubectl:<br /> <br />
shell
curl -O https://s3.us-west-2.amazonaws ... bectl
chmod +x ./kubectl
mkdir -p $HOME/bin && cp ./kubectl $HOME/bin/kubectl && export PATH=$HOME/bin:$PATH
```
配置 EKS 集群环境
我们使用 eksctl 创建一个 1.30 版本的集群,这里通过 YAML 模板定义 EKS 集群的 VPC 网络配置,并根据 eksctl 官方文档调整相关字段。将以下模板保存为my-cluster.yaml
文件:
```yaml创建一个包含 2 个 m5.2xlarge 实例的节点组
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: LAB-1-30
region: ap-northeast-1
vpc:
subnets:
private:
ap-northeast-1a: { id: subnet-11223344 }
ap-northeast-1c: { id: subnet-55667788 }
ap-northeast-1d: { id: subnet-99001122 }
nodeGroups:- name: managed-workers-01
labels: { role: workers }
instanceType: m5.2xlarge
minSize: 2
maxSize: 4
desiredCapacity: 3
privateNetworking: true
volumeSize: 30
<br /> <br /> 通过以下命令创建集群:<br /> <br />
shell
eksctl create cluster -f my-cluster.yaml
<br /> <br /> 集群创建完成后,使用以下命令检查集群是否就绪:<br /> <br />
shell
更新 kubeconfig 的凭证文件
aws eks update-kubeconfig --name LAB-1-30 --region ap-northeast-1
kubectl get node
[ec2-user@ip-10-0-0-84 ~]$ kubectl get node
NAME STATUS ROLES AGE VERSION
ip-10-0-100-132.ap-northeast-1.compute.internal Ready16m v1.30.2-eks-1552ad0
ip-10-0-101-148.ap-northeast-1.compute.internal Ready16m v1.30.2-eks-1552ad0
<br /> <br /> 安装 EBS-CSI-Driver 插件,后续部署时可以指定 StorageClass 来使用亚马逊云的 EBS 块存储服务:<br /> <br />
shell
eksctl utils associate-iam-oidc-provider --region=ap-northeast-1 --cluster=LAB-1-30 --approve
eksctl create iamserviceaccount \
--name ebs-csi-controller-sa \
--namespace kube-system \
--cluster LAB-1-30 \
--region ap-northeast-1 \
--role-name AmazonEKS_EBS_CSI_DriverRole \
--role-only \
--attach-policy-arn arn:aws:iam::aws:policy/service-role/AmazonEBSCSIDriverPolicy \
--approve
eksctl create addon --cluster LAB-1-30 --name aws-ebs-csi-driver --version latest --region ap-northeast-1 \
--service-account-role-arn arn:aws:iam::112233445566:role/AmazonEKS_EBS_CSI_DriverRole --force
[ec2-user@ip-10-0-0-84 ~]$ kubectl get pod -n kube-system | grep -i ebs
ebs-csi-controller-868598b64f-pwmxq 6/6 Running 0 11m
ebs-csi-controller-868598b64f-qn2lz 6/6 Running 0 11m
ebs-csi-node-fplxg 3/3 Running 0 11m
ebs-csi-node-v6qwj 3/3 Running 0 11m
<br /> <br /> 安装 AWS LoadBalancer Controller 组件:<br /> <br />
shell
eksctl create iamserviceaccount \
--cluster=LAB-1-30 \
--region ap-northeast-1 \
--namespace=kube-system \
--name=aws-load-balancer-controller \
--role-name AmazonEKSLoadBalancerControllerRole_130 \
--attach-policy-arn=arn:aws:iam::112233445566:policy/AWSLoadBalancerControllerIAMPolicy \
--approve
helm repo add eks https://aws.github.io/eks-charts
helm repo update eks
wget https://raw.githubusercontent. ... .yaml
kubectl apply -f crds.yaml
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
-n kube-system \
--set clusterName=LAB-1-30 \
--set serviceAccount.create=false \
--set serviceAccount.name=aws-load-balancer-controller \
--set region=ap-northeast-1
验证安装
kubectl get deployment -n kube-system aws-load-balancer-controller
NAME READY UP-TO-DATE AVAILABLE AGE
aws-load-balancer-controller 2/2 2 2 39s
```
至此,我们已经完成了 EKS 集群的配置。
安装 Easysearch 服务
本文中,将通过 AWS LoadBalancer 部署 Console 服务。首先,通过 Helm 将 Console 相关的模板文件拉取到本地,执行以下命令:
shell<br /> helm pull infinilabs/console<br /> tar -zxvf console-0.2.0.tgz<br /> cd console<br />
目录结构如下:
shell<br /> [ec2-user@ip-10-0-0-84 console]$ tree<br /> .<br /> ├── Chart.yaml<br /> ├── templates<br /> │ ├── NOTES.txt<br /> │ ├── _helpers.tpl<br /> │ ├── hpa.yaml<br /> │ ├── ingress.yaml<br /> │ ├── service.yaml<br /> │ ├── serviceaccount.yaml<br /> │ └── statefulset.yaml<br /> └── values.yaml<br />
我们需要修改service.yaml
和values.yaml
中的部分配置:
```yamlserivce.yaml
参考 AWS Load Balancer Controller 的文档,配置负载均衡器面向公网
metadata:
annotations:
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: instance
service.beta.kubernetes.io/aws-load-balancer-subnets: subnet-11223344, subnet-55667788, subnet-9911223344
values.yaml
使用 GP2 StorageClass,并指定 Service Type 为 LoadBalancer
service:
type: LoadBalancer
storageClassName: gp2
<br /> <br /> 使用 Helm 部署 console 服务:<br /> <br />
shell
kubectl create ns Easysearch
helm upgrade --install console . -f values.yaml -n Easysearch
检查是否创建了 Service 并获取负载均衡器的 DNS 地址
kubectl get svc -n Easysearch
NAME TYPE CL
USTER-IP EXTERNAL-IP PORT(S) AGE
console LoadBalancer 172.20.237.237 k8s-xxxx.elb.ap-northeast-1.amazonaws.com 9000:32190/TCP 6h49m
<br /> <br /> 接下来是创建 Easysearch 单节点集群服务。创建一个新的 `values.yaml` 文件并定义使用 GP2 类型的 StorageClass,如下:<br /> <br />
shell
cd ~
echo 'storageClassName: gp2' > values.yaml
cat << EOF | kubectl apply -n Easysearch -f -
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: Easysearch-ca-issuer
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: Easysearch-ca-certificate
spec:
commonName: Easysearch-ca-certificate
duration: 87600h0m0s
isCA: true
issuerRef:
kind: Issuer
name: Easysearch-ca-issuer
privateKey:
algorithm: ECDSA
size: 256
renewBefore: 2160h0m0s
secretName: Easysearch-ca-secret
EOF
helm install Easysearch infinilabs/Easysearch -n Easysearch -f values.yaml
<br /> <br /> 至此,我们已在 AWS EKS 平台上完成了 Easysearch 的部署。可以通过 Kubernetes 中的 Service DNS 地址在 Console 中验证连接到内部的 Easysearch 服务。本文中使用的地址为:`Easysearch.Easysearch.svc.cluster.local:9200`。<br /> <br /> 也可以在 Easysearch 的 Pod 中使用命令进行连接验证:<br /> <br />
shell
kubectl exec -n Easysearch Easysearch-0 -it -- curl -ku 'admin:admin' https://Easysearch.Easysearch. ... :9200
{
"name" : "Easysearch-0",
"cluster_name" : "infinilabs",
"cluster_uuid" : "fq3r_ZaHSFuZDjDtKyJY_w",
"version" : {
"distribution" : "Easysearch",
"number" : "1.6.0",
"distributor" : "INFINI Labs",
"build_hash" : "e5d1ff9067b3dd696d52c61fbca1f8daed931fb7",
"build_date" : "2023-09-22T00:55:32.292580Z",
"build_snapshot" : false,
"lucene_version" : "8.11.2",
"minimum_wire_lucene_version" : "7.7.0",
"minimum_lucene_index_compatibility_version" : "7.7.0"
},
"tagline" : "You Know, For Easy Search!"
}
```
总结
通过本文的实践操作,我们成功地在 AWS EKS 平台上部署了 Easysearch 服务,验证了其在云环境中的高效运行能力。从 EKS 集群的配置、存储和网络资源的准备,到最终的 Easysearch 部署与测试,整个过程展示了如何利用 AWS 提供的工具和服务,快速构建企业级搜索引擎解决方案。
通过这次部署,我们不仅了解了 Easysearch 在 Kubernetes 环境中的部署方法,还深入体验了 AWS EKS 平台的强大功能。未来,随着企业数据量的不断增长,结合云计算的弹性和容器化技术的优势,将会为企业的数据管理和搜索提供更加高效的解决方案。
参考文档
- name: managed-workers-01
- [AWS 命令行界面](https://aws.amazon.com/cn/cli/)
- [Helm](https://helm.sh/)
- [eksctl](https://eksctl.io/)
- [Helm Chart 部署 Easysearch](https://infinilabs.cn/docs/lat ... /helm/)
关于 Easysearch 有奖征文活动

无论你是 Easysearch 的老用户,还是第一次听说这个名字,只要你对 INFINI Labs 旗下的 Easysearch 产品感兴趣,或者是希望了解 Easysearch,都可以参加这次活动。
详情查看:[Easysearch 征文活动](https://infinilabs.cn/blog/202 ... ukong/)
作者:韩旭,亚马逊云技术支持,亚马逊云科技技领云博主,目前专注于云计算开发和大数据领域。
原文:https://infinilabs.cn/blog/202 ... -eks/
从 Elasticsearch 到 Easysearch:国产搜索型数据库的崛起与未来展望
INFINI Labs 小助手 发表了文章 • 0 个评论 • 5383 次浏览 • 2024-08-14 12:17

1. 引言:数据库的定义与作用
1.1 数据库的定义
数据库是一个专门用于组织、存储和管理数据的系统(Database System,简称 DBS),它以高效的方式为用户提供数据的存储、访问和管理功能。数据库的定义涵盖了各种数据模型和结构,主要可以分为关系型数据库(RDBMS)和非关系型数据库(NoSQL)两大类。

- 关系型数据库:以二维表格的形式组织数据,通过主键、外键来维持表与表之间的关系。这种数据库模型擅长处理结构化数据,并且通过 SQL(Structured Query Language)来管理数据。其最大的优势在于数据的一致性和完整性,但在处理大量非结构化数据时可能表现不佳。
- 非关系型数据库:也称为 NoSQL 数据库,适合存储和处理非结构化或半结构化数据,如文档、键值对、图形和列族等。NoSQL 数据库通常具有更高的灵活性和扩展性,尤其适合处理大规模分布式数据集和实时数据处理任务。
1.2 数据库在现代计算中的作用
在现代计算环境中,数据库是信息系统的核心。无论是互联网企业,还是传统行业的数字化转型,都依赖于强大的数据库系统来支撑各种应用程序的运行。数据库的作用包括:
- 数据存储:数据库能够安全地存储大规模数据,无论是结构化数据如表格,还是非结构化数据如图像和文本。
- 数据管理:数据库提供了复杂的查询、排序、更新、删除等操作,确保数据可以被有效地管理和利用。
- 数据分析:借助数据库中的索引和搜索功能,用户可以对海量数据进行快速检索和分析,从而支持实时决策和业务优化。
- 数据安全:数据库系统通常包含访问控制、加密、备份和恢复等功能,保护数据的机密性、完整性和可用性。
数据库已经成为现代企业运作的基石,为电子商务、社交媒体、金融服务、健康医疗等领域提供了不可或缺的数据支持。
2. 数据库的演变
2.1 关系型数据库的崛起
数据库的发展主要历经三个阶段,前关系型、关系型和后关系型。

20 世纪 70 年代,埃德加·科德提出了关系型数据库模型的概念,这一创新彻底改变了数据管理的方式。关系型数据库以关系代数为理论基础,将数据组织为多个相互关联的二维表格,这种模型极大简化了数据存储与检索的复杂性。
- 表格结构:数据以表的形式存储,每个表由行和列组成,行代表记录,列代表字段。表与表之间通过主键和外键来建立关系。
- SQL 的引入:为了管理关系型数据库,科德引入了结构化查询语言(SQL),这是一种强大的数据操作语言,允许用户通过简单的语句执行复杂的查询操作。
- 数据的一致性和完整性:关系型数据库通过事务处理机制(ACID 特性:原子性、一致性、隔离性和持久性),确保数据在并发操作和系统故障情况下保持一致性和完整性。
由于其高效的数据管理能力和强大的查询功能,关系型数据库迅速成为企业级应用的主流选择,在银行、保险、制造业等领域得到了广泛应用。
2.2 关系型数据库的局限性
随着信息技术的飞速发展,数据量呈现爆炸式增长,数据类型也日益多样化,这使得关系型数据库逐渐暴露出其局限性。
- 扩展性不足:关系型数据库通常依赖垂直扩展(增加单个服务器的硬件能力)来提升性能,但这种方式在面对海量数据时成本高昂且效率有限。而对于需要分布式处理的大规模数据集,关系型数据库的横向扩展能力(增加服务器节点)较弱,难以满足分布式系统的需求。
- 非结构化数据处理困难:关系型数据库擅长处理结构化数据,但对于文本、图像、视频等非结构化数据的处理效率较低,需要额外的处理步骤和存储空间。这种局限性使其在面对现代大数据环境时显得捉襟见肘。
- 灵活性不足:关系型数据库的表结构和模式是预定义的,这意味着在数据模型发生变化时,修改数据库结构的成本和风险都较高,影响了系统的灵活性和适应性。
这些局限性推动了新型数据库技术的发展,尤其是 NoSQL 数据库的兴起,它们能够更好地处理分布式环境下的大规模非结构化数据。
3. 搜索型数据库的兴起
3.1 非结构化数据处理的需求
随着互联网和信息技术的发展,数据的类型和规模发生了巨大变化。除了传统的结构化数据,非结构化数据(如文本、图像、音频、视频等)也在迅速增长。这类数据并不适合存储在传统的关系型数据库中,因为它们无法以固定的表格形式进行有效的组织和管理。
在这种背景下,企业和组织对非结构化数据的处理和分析需求日益强烈。例如,社交媒体平台需要实时分析大量用户生成的文本内容,电子商务网站需要对用户的搜索和购买历史进行个性化推荐。这些需求促使数据库技术朝着更灵活和高效的方向发展。
为了应对这一挑战,NoSQL 数据库应运而生。NoSQL 数据库不依赖于固定的表格结构,而是支持多种数据模型,如文档、键值对、列族和图数据库等。它们在处理大规模分布式数据和非结构化数据时表现优异,尤其是在扩展性和灵活性方面。
然而,随着搜索需求的日益复杂,简单的 NoSQL 数据库已无法满足企业对快速全文检索、实时分析以及复杂查询的需求。这时,搜索型数据库逐渐成为焦点。它们不仅能够处理大规模数据,还能在数秒内从庞大的数据集中检索出相关信息,大大提升了数据的利用价值。
3.2 搜索型数据库的定义与特点
搜索型数据库是一类专门设计用于处理和检索大量非结构化数据的数据库系统。与传统的关系型数据库不同,搜索型数据库的主要功能是快速、准确地进行全文检索和复杂查询,尤其是在处理文本数据时表现出色。
核心技术与特点:
- 倒排索引:这是搜索型数据库的核心技术,它通过为每个单词建立索引来加速查询过程。当用户输入查询时,系统可以直接通过索引定位相关文档,而无需逐个扫描整个数据库。
- 分布式架构:搜索型数据库通常采用分布式架构,以便能够处理大规模的数据集。它们将数据分布在多个节点上,确保即使在高并发或大数据量的情况下,系统仍然能够高效运行。
- 实时数据处理:现代搜索型数据库不仅支持批量数据处理,还能处理实时数据,这使得它们非常适合用于日志管理、监控和数据流分析等场景。
- 可扩展性:由于采用了分布式设计,搜索型数据库可以通过增加节点轻松扩展,从而处理日益增长的数据量和查询需求。
通过这些特点,搜索型数据库已经成为处理海量非结构化数据的关键工具,为企业和组织提供了强大的数据检索和分析能力。
4. Elasticsearch:革命性的搜索型数据库
4.1 Elasticsearch 的背景与发展

Elasticsearch 是由 Shay Banon 于 2010 年基于开源搜索引擎库 Apache Lucene 开发的。它的出现,标志着搜索型数据库进入了一个新的时代。Elasticsearch 旨在为现代数据驱动的应用程序提供高效、灵活的搜索和分析功能。由于其强大的功能和易用性,Elasticsearch 迅速在全球范围内获得了广泛的采用。
Elasticsearch 的诞生源于对大规模数据处理和全文检索的需求。随着互联网的快速发展,企业需要一种能够高效处理和搜索海量数据的工具,而传统的关系型数据库和早期的 NoSQL 解决方案无法满足这一需求。Elasticsearch 在此背景下应运而生,成为解决这些挑战的理想选择。
4.2 核心特性与架构
Elasticsearch 之所以能够在众多搜索型数据库中脱颖而出,主要得益于其强大的核心特性和先进的架构设计。
核心特性:
- 分布式架构:Elasticsearch 的分布式设计使其能够在多个节点上分片存储数据,从而实现高可用性和可扩展性。每个分片都是一个独立的搜索引擎,可以在多个节点之间进行复制,以确保数据的冗余和安全。
- RESTful API:Elasticsearch 提供了一个易于使用的 RESTful API,开发者可以通过简单的 HTTP 请求与其进行交互。这种设计使得 Elasticsearch 可以轻松集成到各种应用程序中。
- 实时索引和搜索:Elasticsearch 支持实时数据索引,这意味着数据在写入后几乎可以立即被搜索到。这一特性使其非常适合用于日志管理、监控和实时分析等需要快速响应的场景。
- 灵活的查询语言:Elasticsearch 提供了功能强大的查询 DSL(Domain Specific Language),允许用户进行复杂的查询操作,如布尔查询、范围查询、模糊查询等。它还支持聚合查询,使用户能够对数据进行高级分析。
架构设计:
Elasticsearch 的架构基于分片(Shard)和副本(Replica)的概念。每个索引被划分为若干个分片,每个分片可以有一个或多个副本。这种设计不仅提高了数据的可用性和容错性,还使得系统能够轻松处理大规模数据集。
此外,Elasticsearch 还使用了 Apache Lucene 作为底层搜索库,充分利用了 Lucene 强大的全文检索能力和索引机制。这使得 Elasticsearch 在处理复杂搜索任务时表现得非常高效。
4.3 典型应用场景
Elasticsearch 在多个行业和场景中得到了广泛应用,其灵活性和强大的搜索能力使其成为许多企业的首选解决方案。
- 日志和基础设施监控:在 IT 运维中,Elasticsearch 常用于收集和分析系统日志、应用日志和安全日志。通过与 Kibana(一个开源的分析和可视化平台)结合,用户可以实时监控系统状态,并快速识别和解决问题。
- 企业搜索:Elasticsearch 被广泛应用于企业内部文档和数据的搜索管理。无论是知识管理系统还是文档管理平台,Elasticsearch 都能够提供高效的全文检索和信息聚合能力,帮助企业提升工作效率。
- 电子商务搜索:在电子商务领域,Elasticsearch 用于实现快速、精确的产品搜索和推荐系统。它不仅可以处理大量产品数据,还能根据用户行为提供个性化推荐,提升用户体验和转化率。
5. Elasticsearch 的挑战与发展
5.1 扩展性问题
尽管 Elasticsearch 在处理大规模数据方面表现优异,但在面对极端大规模的应用场景时,其扩展性仍然是一个挑战。由于分布式系统的复杂性,网络分区、节点故障等问题可能导致数据不一致,甚至影响系统的整体性能。
为了应对这些挑战,开发者们引入了多种扩展性优化措施,例如改进分片管理策略、优化分布式查询算法等。这些改进旨在提高 Elasticsearch 在大规模集群中的稳定性和效率,但随着数据量的持续增长,扩展性问题仍然是一个需要持续关注和解决的问题。
5.2 性能优化
随着使用 Elasticsearch 的企业和应用越来越多,性能优化成为了一个关键议题。为了保证 Elasticsearch 在大规模数据处理中的高效性,开发者们采取了多种优化手段,包括改进索引策略、调整缓存机制、优化查询执行路径等。
此外,为了满足不同场景下的性能需求,Elasticsearch 还引入了多种配置选项,允许用户根据具体应用场景进行调整。例如,通过调整分片数量和副本数,用户可以在性能和数据冗余之间找到平衡。
5.3 安全与合规
随着全球数据隐私和安全法律法规的日益严格,Elasticsearch 在安全和合规性方面的挑战也日益凸显。企业在使用 Elasticsearch 时,必须确保数据的安全性和合规性,尤其是在处理敏感数据时。
为了解决这些问题,Elasticsearch 提供了一系列安全功能,如访问控制、数据加密、审计日志等。此外,开发者们还可以通过配置和插件,实现更高级别的安全措施,以满足特定行业和地区的合规要求。
但是,Elasticsearch 的安全性和合规性仍然是一个需要不断优化的领域。近几年 ES 数据泄露事件频发,很多 ES 库连基本的安全认证都没有,导致很多企业直接把 ES 当做存储库,数据泄露后直接被黑客利用。
结合今年 OpenAi 停止对中国内地和香港地区提供 API 服务可以看出,依赖国外技术可能带来技术封锁风险,一旦国外企业因政治或经济原因停止服务,中国企业的业务连续性和数据安全性将受到威胁。
6. 国内搜索型数据库的发展
6.1 中国搜索数据库的发展背景
随着国家对科技自主创新的重视,中国的数据库技术在过去十年中取得了显著进展。尤其是在中美技术竞争加剧的背景下,减少对国外技术的依赖成为了中国科技发展的战略目标。这种背景促使了国产数据库的加速发展,特别是在搜索型数据库领域。众多中国企业开始自主研发具备核心技术的数据库产品,试图在这一领域实现突破。
政策推动与市场需求
中国政府出台了一系列政策,鼓励本土企业在关键技术领域实现自主可控。这些政策不仅为企业提供了资金支持和政策优惠,还明确了在一些关键行业中优先使用国产软件的导向。同时,随着中国企业在互联网、电子商务、智能制造等领域的快速发展,对高效搜索和数据处理的需求愈发迫切,这也成为国产搜索型数据库发展的强大推动力。
6.2 Easysearch 的兴起

在此背景下,Easysearch 作为中国本土开发的搜索型数据库脱颖而出。Easysearch 的设计目标是为中国企业提供一个高效、可靠且适应本土需求的搜索与数据分析解决方案。与国外的 Elasticsearch 相似,Easysearch 基于分布式架构和倒排索引技术,能够处理大规模数据,并支持复杂的全文搜索和分析。
然而,Easysearch 并非只是简单的模仿或复制 Elasticsearch。它在多个方面进行了本地化优化,以更好地适应中国市场的独特需求。例如,在处理中文文本时,Easysearch 针对中文的特殊语法结构进行了优化,增强了中文分词的准确性和查询效率。此外,Easysearch 还在性能和可扩展性上进行了改进,使其能够更好地应对大规模企业级应用的需求。
不仅如此,Easysearch 还是国内首个通过搜索型数据库产品能力测试的国产搜索型数据库。自 2023 年 10 月起,Easysearch 凭借其卓越的性能和深度的本土化优化,成功在墨天轮搜索型数据库排行榜上长期占据榜首位置。这一成绩不仅体现了 Easysearch 在技术层面的突破,也反映了市场对其产品的高度认可。在短短几个月的时间里,Easysearch 以其稳定的表现和不断创新的步伐,赢得了众多企业用户的信赖。


6.3 Easysearch 与 Elasticsearch 的对比
虽然 Easysearch 与 Elasticsearch 在架构和基本功能上有很多相似之处,但它们在具体的实现和应用场景中表现出了一些显著的差异。
- 中文文本处理:Elasticsearch 虽然支持多语言环境,但其在中文处理上的表现并不如 Easysearch 那么出色。Easysearch 针对中文的语法和分词进行了专门的优化,尤其是在处理同义词、短语匹配和模糊查询时,能够提供更高的准确性。
- 本地化支持:Easysearch 提供了更强的本地化支持,包括符合中国法律法规的安全和合规性功能。此外,它还集成了许多国内常用的第三方系统,简化了企业的集成和部署过程。
- 性能优化:在处理大规模数据集时,Easysearch 通过定制化的优化策略,如特定的索引压缩技术和内存管理方案,提升了系统的响应速度和资源利用率。这使得它在某些特定应用场景下,能够提供比 Elasticsearch 更高的性能和稳定性。
- 安全可靠:Easysearch 提供了多种安全和合规性功能,如 TLS 加密、磁盘加密等。此外,它还支持多种第三方认证方式,如 LDAP、AD
6.4 国产搜索型数据库的未来
根据第一新声研究,2022-2027 年中国数据库整体市场将维持增长态势 ,2024 年整体市场规模预计为 543.1 亿,到 2027 年将增长至 1183.8 亿,2022-2027 年复合增长率达到 30.67%。

随着全球对数据安全和本地化需求的不断增加,国产搜索型数据库在未来有望占据更大的市场份额。
Easysearch 及其他国产数据库将进一步提升技术水平,持续创新,以满足不断变化的市场需求。
全球化与竞争力
虽然当前 Easysearch 主要面向国内市场,但其潜在的全球化前景不容小觑。通过持续的技术创新和市场拓展,Easysearch 及其他国产数据库有望在全球范围内与国际巨头展开竞争,特别是在亚非拉等新兴市场。这不仅有助于提升中国数据库技术的国际影响力,也将推动全球数据库产业的多样化发展。
7. 结论
通过对搜索型数据库的发展历程和未来趋势的探讨,可以看出,随着大数据和人工智能技术的不断进步,搜索型数据库将在更多领域发挥重要作用。Elasticsearch 作为全球领先的搜索型数据库,其开创性的架构和功能为行业树立了标杆。而以 Easysearch 为代表的国产数据库,也正在迅速崛起,展现出强大的竞争力。未来,搜索型数据库将继续朝着多模态、智能化、本地化的方向发展,为全球信息技术的发展提供更加坚实的基础。
参考资料
- [搜索引擎数据库](https://blog.csdn.net/hgstclyh ... 314739)
- [搜索型数据库的技术发展历程与趋势前瞻](https://infinilabs.cn/blog/202 ... bases/)
- [数据库行业分析:国产数据库百花齐放,搜索引擎数据库风口已至](https://new.qq.com/rain/a/20221123A01V1F00)
- [浅谈搜索引擎和传统数据库(ES,solr)](https://blog.csdn.net/weixin_4 ... 643504)
- [什么是 Elasticsearch?](https://www.ibm.com/cn-zh/topics/elasticsearch)
- [INFINI Labs 产品更新 | 重磅推出 Easysearch v1.1](https://infinilabs.cn/blog/2023/release-20230515/)
- [墨天轮中国数据库流行度排行](https://www.modb.pro/dbRank)
- [喜讯!INFINI Easysearch 在墨天轮搜索型数据库排名中荣登榜首](https://infinilabs.cn/blog/2023/news-20230913/)
- [《2024 年中国数据库市场研究报告》重磅发布 | 第一新声](https://news.sina.com.cn/shang ... .shtml)
- [国内首家 | 极限科技率先完成信通院搜索型数据库行业标准测试](http://localhost:1313/blog/202 ... ducts/)
- [危险!超 9000 个 Elasticsearch 集群暴露在公网上](https://infinilabs.cn/blog/202 ... ernet/)
- [从 OpenAI 停服看中国市场:国产替代崛起的机遇与挑战](https://infinilabs.cn/blog/202 ... ising/)
- [什么是数据库](https://aws.amazon.com/cn/what-is/database/)
- [数据库发展史](https://blog.csdn.net/double22 ... 6.235^v43^pc_blog_bottom_relevance_base5&spm=1001.2101.3001.4242.1&utm_relevant_index=1)
关于 Easysearch 有奖征文活动

无论你是 Easysearch 的老用户,还是第一次听说这个名字,只要你对 INFINI Labs 旗下的 Easysearch 产品感兴趣,或者是希望了解 Easysearch,都可以参加这次活动。
详情查看:[Easysearch 征文活动](https://infinilabs.cn/blog/202 ... ukong/)
作者:李家兴
原文:https://infinilabs.cn/blog/202 ... ases/
- [搜索引擎数据库](https://blog.csdn.net/hgstclyh ... 314739)
【第2期】INFINI Easysearch 免费认证培训开放报名啦
INFINI Labs 小助手 发表了文章 • 0 个评论 • 3257 次浏览 • 2024-08-09 16:55
探索 Easysearch 的无限可能,与 INFINI Labs 共赴搜索技术前沿!
随着数字化转型的加速,搜索技术已成为企业数据洞察的核心。INFINI Labs 作为搜索创新技术的引领者,诚邀所有对 Easysearch 搜索引擎感兴趣的开发者、技术爱好者及合作伙伴,参加我们即将于 2024 年 8 月 17 日至 18 日举办的 第二期 Easysearch 线上免费培训活动。这不仅是一场知识的盛宴,更是技能提升的加速器,将助您在职业道路上迈出坚实的一步!
活动亮点
- 系统课程,全面深入:从 Easysearch 的基本概念到环境搭建,再到高级功能的实战应用,INFINI Labs 的技术专家将为您带来全面而深入的讲解,确保每位参与者都能收获满满。
- 实战导向,解决痛点:课程设计紧贴实际需求,旨在帮助学员掌握 Easysearch 的核心技术,有效解决工作中的搜索需求和技术难题,让理论知识迅速转化为实践能力。
- 认证证书,助力进阶:后期 INFINI Labs 将推出 Easysearch 认证考试。通过考试的学员将获得官方认证的 Easysearch 证书,为您的职业发展增添强力背书,开启职业生涯的新篇章。
培训时间
2024 年 8 月 17 日至 18 日(周六、周日)共两天,每天具体培训时间:
- 上午 09:30 ~ 11:30
- 下午 14:00 ~ 16:00
培训内容概览
第一阶段:初识 Easysearch
- Easysearch 环境搭建与对比,了解其与 Elasticsearch 的差异;
- 功能初探:身份验证、数据脱敏、权限控制等,全面掌握 Easysearch 的基础功能;
- 容灾技术:兼容性验证、跨集群复制等,确保您的搜索服务稳定可靠;
第二阶段:Easysearch 高阶使用
- 深度探析:性能压测、数据迁移、请求管理等,提升 Easysearch 的使用效率;
- 高级功能:快照管理、可视化看板、告警功能等,让您的搜索服务更加智能;
- 生态集成:Filebeat、Logstash、LangChain 等,轻松实现 Easysearch 与其他工具的集成;
参与方式
本次活动完全免费,名额有限,请尽快报名,同时微信扫码添加小助手进群(培训会议地址将在微信群公布),锁定您的学习席位!
扫码或点击 [我要报名](https://3884926668399.huodongx ... 314822)

👉 立即行动:不要错过这次提升自我、与行业精英共成长的宝贵机会。让我们相聚云端,共同探索 Easysearch 的无限可能,开启技术进阶的新篇章!
参会提示
- 培训内容涉及动手实践,请务必自备电脑(Windows 系统环境请提前安装好 Linux 虚拟机);
- 请提前在 INFINI Labs 官网下载对应平台最新安装包(INFINI Easysearch、INFINI Gateway、INFINI Console);
- 下载地址:[https://infinilabs.cn/download](https://infinilabs.cn/download)
联系我们
如有任何疑问,欢迎通过微信添加 [小助手:INFINI-Labs] 与我们联系。
INFINI Labs 期待与您相约,共赴这场技术盛宴!
关于 Easysearch

Easysearch 是一个分布式的近实时搜索与分析引擎,基于开源的 Apache Lucene 构建。它旨在提供一个自主可控、轻量级的 Elasticsearch 可替代版本,并不断完善和支持更多的企业级功能。与 Elasticsearch 相比,Easysearch 更注重搜索业务场景的优化,同时保持其产品的简洁与易用性。
详情参见:[Easysearch 介绍](https://infinilabs.cn/products/easysearch)
Easysearch 有奖征文活动推荐

无论你是 Easysearch 的老用户,还是第一次听说这个名字,只要你对 INFINI Labs 旗下的 Easysearch 产品感兴趣,或者是希望了解 Easysearch,都可以参加这次活动。
详情查看:[Easysearch 征文活动](https://infinilabs.cn/blog/202 ... ukong/)
关于极限科技(INFINI Labs)

极限科技,全称极限数据(北京)科技有限公司,是一家专注于实时搜索与数据分析的软件公司。旗下品牌极限实验室(INFINI Labs)致力于打造极致易用的数据探索与分析体验。
极限科技是一支年轻的团队,采用天然分布式的方式来进行远程协作,员工分布在全球各地,希望通过努力成为中国乃至全球企业大数据实时搜索分析产品的首选,为中国技术品牌输出添砖加瓦。
官网:[https://infinilabs.cn](https://infinilabs.cn)
Easysearch、Elasticsearch、Amazon OpenSearch 快照兼容对比
INFINI Labs 小助手 发表了文章 • 2 个评论 • 4001 次浏览 • 2024-07-29 11:54
在当今的数据驱动时代,搜索引擎的快照功能在数据保护和灾难恢复中至关重要。本文将对 Easysearch、Elasticsearch 和 Amazon OpenSearch 的快照兼容性进行比较,分析它们在快照创建、恢复、存储格式和跨平台兼容性等方面的特点,帮助大家更好地理解这些搜索引擎的差异,从而选择最适合自己需求的解决方案。
启动集群
Easysearch
服务器一般情况下默认参数都是很低的,而 Easysearch/Elasticsearch 是内存大户,所以就需要进行系统调优。
bash<br /> sysctl -w vm.max_map_count=262144<br />
vm.max_map_count
是一个 Linux 内核参数,用于控制单个进程可以拥有的最大内存映射区域(VMA,Virtual Memory Areas)的数量。内存映射区域是指通过内存映射文件或匿名内存映射创建的虚拟内存区域。
这个参数在一些应用程序中非常重要,尤其是那些需要大量内存映射的应用程序,比如 Elasticsearch。Elasticsearch 使用内存映射文件来索引和搜索数据,这可能需要大量的内存映射区域。如果 vm.max_map_count
设置得太低,Elasticsearch 可能无法正常工作,并会出现错误信息。
调整 vm.max_map_count
参数的一些常见原因:
- 支持大型数据集:
应用程序(如 Elasticsearch)在处理大型数据集时可能需要大量内存映射区域。增加vm.max_map_count
可以确保这些应用程序有足够的内存映射区域来处理数据。
- 防止内存错误:
如果vm.max_map_count
设置得太低,当应用程序尝试创建超过限制的内存映射时,会出现错误,导致应用程序崩溃或无法正常工作。
- 优化性能:
适当地设置vm.max_map_count
可以优化应用程序的性能,确保内存映射操作顺利进行。
检查当前的vm.max_map_count
值:
bash<br /> sysctl vm.max_map_count<br />
或者查看/proc/sys/vm/max_map_count
文件:
bash<br /> cat /proc/sys/vm/max_map_count<br />
Elasticsearch 官方建议将vm.max_map_count
设置为至少 262144。对于其他应用程序。
Easysearch 具体安装步骤见 [INFINI Easysearch 尝鲜 Hands on](https://blog.csdn.net/weixin_3 ... 077785)
Amazon OpenSearch
使用 Amazon Web Services 控制台进行创建。
Elasticsearch
使用如下 docker compose 部署一个三节点的 ES 集群:
```yml
version: "2.2"
services:
es01:
image: docker.elastic.co/elasticsearch/elasticsearch:7.10.2
container_name: es01
environment:- node.name=es01
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es02,es03
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes: - data01:/usr/share/elasticsearch/data
ports: - 9200:9200
networks: - elastic
es02:
image: docker.elastic.co/elasticsearch/elasticsearch:7.10.2
container_name: es02
environment: - node.name=es02
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es03
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes: - data02:/usr/share/elasticsearch/data
networks: - elastic
es03:
image: docker.elastic.co/elasticsearch/elasticsearch:7.10.2
container_name: es03
environment: - node.name=es03
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es02
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes: - data03:/usr/share/elasticsearch/data
networks: - elastic
volumes:
data01:
driver: local
data02:
driver: local
data03:
driver: local
networks:
elastic:
driver: bridge
```
由于这个 docker compose 没有关于 kibana 的配置,所以我们还是用 Console 添加原生的 Elasticsearch 集群!

集群信息

快照还原的步骤
快照前的准备
插件安装
本次测试选择把索引快照备份到 Amazon S3,所以需要使用 S3 repository plugin,这个插件添加了对使用 Amazon S3 作为快照/恢复存储库的支持。
Easysearch 和 OpenSearch 集群自带了这个插件,所以无需额外安装。
对于自己部署的三节点 Elasticsearch 则需要进入每一个节点运行安装命令然后再重启集群,建议使用自动化运维工具来做这步,安装命令如下:
bash<br /> sudo bin/elasticsearch-plugin install repository-s3<br />
如果不再需要这个插件,可以这样删除。
bash<br /> sudo bin/elasticsearch-plugin remove repository-s3<br />
由于需要和 Amazon Web Services 打交道,所以我们需要设置 IAM 凭证,这个插件可以从 EC2 IAM instance profile,ECS task role 以及 EKS 的 Service account 读取相应的凭证。
对于托管的 Amazon OpenSearch 来说,我们无法在托管的 EC2 上绑定我们的凭证,所以需要新建一个 OpenSearchSnapshotRole,然后通过当前的用户把这个角色传递给服务,也就是我们说的 IAM:PassRole。
创建 OpenSearchSnapshotRole,策略如下:
bash<br /> {<br /> "Version": "2012-10-17",<br /> "Statement": [{<br /> "Action": [<br /> "s3:ListBucket"<br /> ],<br /> "Effect": "Allow",<br /> "Resource": [<br /> "arn:aws:s3:::bucket-name"<br /> ]<br /> },<br /> {<br /> "Action": [<br /> "s3:GetObject",<br /> "s3:PutObject",<br /> "s3:DeleteObject"<br /> ],<br /> "Effect": "Allow",<br /> "Resource": [<br /> "arn:aws:s3:::bucket-name/*"<br /> ]<br /> }<br /> ]<br /> }<br />
信任关系如下:
json<br /> {<br /> "Version": "2012-10-17",<br /> "Statement": [<br /> {<br /> "Effect": "Allow",<br /> "Principal": {<br /> "Service": "es.amazonaws.com"<br /> },<br /> "Action": "sts:AssumeRole"<br /> }<br /> ]<br /> }<br />
然后在我们的 IAM user 上加上 PassRole 的权限,这样我们就可以把 OpenSearchSnapshotRole 传递给 OpenSearch 集群。
json<br /> {<br /> "Version": "2012-10-17",<br /> "Statement": [<br /> {<br /> "Effect": "Allow",<br /> "Action": "iam:PassRole",<br /> "Resource": "arn:aws:iam::123456789012:role/OpenSearchSnapshotRole"<br /> }<br /> ]<br /> }<br />
注册存储库
在源集群执行注册
json<br /> PUT /_snapshot/snapshot-repo-name<br /> {<br /> "type": "s3",<br /> "settings": {<br /> "bucket": "<bucket-name>",<br /> "base_path": "<bucket-prefix>",<br />
在目标集群同样执行这个语句,为了防止覆盖源集群存储库的数据,将 "readonly": true 添加到"settings" PUT 请求中,这样就只有一个集群具有对存储库的写入权限。
json<br /> PUT /_snapshot/snapshot-repo-name<br /> {<br /> "type": "s3",<br /> "settings": {<br /> "bucket": "<bucket-name>",<br /> "base_path": "<bucket-prefix>",<br /> "readonly": true,<br />
对于 OpenSearch 来说,还需要执行 passrole,所以还需要添加role_arn这个字段,由于 IAM:PassRole 需要对 HTTP 请求做 signV4 日签名,所以这部常常使用 Postman 来完成。把角色传递过去之后,接下来的快照还原操作就可以在 OpenSearch Dashboard 中进行操作了。

需要注意的是,需要在 auth 这里输入 AccessKey,SecretKey,AWS Region,Service Name(es)来做 SignV4 的签名。

请求体如下:
json<br /> {<br /> "type": "s3",<br /> "settings": {<br /> "bucket": "<bucket-name>",<br /> "base_path": "<bucket-prefix>",<br /> "readonly": true,<br /> "role_arn": "arn:aws:iam::123456789012:role/OpenSearchSnapshotRole"<br /> }<br /> }<br />
- 查看所有注册的存储库:
GET _snapshot
:这个命令返回所有已注册的快照存储库列表及其基本信息。
sh<br /> GET _snapshot<br />
json<br /> {<br /> "es_repository": {<br /> "type": "s3",<br /> "settings": {<br /> "bucket": "your-s3-bucket-name",<br /> "region": "your-s3-bucket-region"<br /> }<br /> }<br /> }<br />
- 查看特定存储库的详细信息:
GET _snapshot/es_repository
:这个命令返回名为es_repository
的存储库的详细配置信息,包括存储桶名称、区域和其他设置。
sh<br /> GET _snapshot/es_repository<br />
json<br /> {<br /> "es_repository": {<br /> "type": "s3",<br /> "settings": {<br /> "bucket": "your-s3-bucket-name",<br /> "region": "your-s3-bucket-region",<br /> "access_key": "your-access-key",<br /> "secret_key": "your-secret-key"<br /> }<br /> }<br /> }<br />
- 查看特定存储库中的快照:
GET _cat/snapshots/es_repository?v
:这个命令返回es_repository
存储库中的所有快照及其详细信息,包括快照 ID、状态、开始时间、结束时间、持续时间、包含的索引数量、成功和失败的分片数量等。
sh<br /> GET _cat/snapshots/es_repository?v<br />
plaintext<br /> id status start_epoch start_time end_epoch end_time duration indices successful_shards failed_shards total_shards<br /> snapshot_1 SUCCESS 1628884800 08:00:00 1628888400 09:00:00 1h 3 10 0 10<br /> snapshot_2 SUCCESS 1628971200 08:00:00 1628974800 09:00:00 1h 3 10 0 10<br />
创建索引快照
```bashPUT _snapshot/my_repository/<mysnapshot{now/d}>
PUT _snapshot/my_repository/my_snapshot
{
"indices": "my-index,logs-my_app-default",
}
<br /> <br /> 根据快照的大小不同,完成快照可能需要一些时间。默认情况下,create snapshot API 只会异步启动快照过程,该过程在后台运行。要更改为同步调用,可以将 `wait_for_completion` 查询参数设置为 `true`。<br /> <br />
bash
PUT _snapshot/my_repository/my_snapshot?wait_for_completion=true
<br /> <br /> 另外还可以使用 clone snapshot API 克隆现有的快照。要监控当前正在运行的快照,可以使用带有 `_current` 请求路径参数的 get snapshot API。<br /> <br />
bash
GET _snapshot/my_repository/_current
<br /> <br /> 如果要获取参与当前运行快照的每个分片的完整详细信息,可以使用 get snapshot status API。<br /> <br />
bash
GET _snapshot/_status
<br /> <br /> 成功创建快照之后,就可以在 S3 上看到备份的数据块文件,这个是正确的快照层级结构:<br /> <br /> <br /> <br /> 需要注意的是, "base_path": "<bucket-prefix>"这里最好不要加/,虽然不影响同集群迁移,这个会为我们在不同厂商的搜索引擎中迁移遇到问题,可能是这样的,所以需要注意。<br /> <br /> <br /> <br /> 所以在 Open Search 中还原 Elasticsearch 就遇到了这个问题:<br /> <br />
json
{
"error": {
"root_cause": [
{
"type": "snapshot_missing_exception",
"reason": "[easy_repository:2/-jOQ0oucQDGF3hJMNz-vKQ] is missing"
}
],
"type": "snapshot_missing_exception",
"reason": "[easy_repository:2/-jOQ0oucQDGF3hJMNz-vKQ] is missing",
"caused_by": {
"type": "no_such_file_exception",
"reason": "Blob object [11111/indices/7fv2zAi4Rt203JfsczUrBg/meta-YGnzxZABRBxW-2vqcmci.dat] not found: The specified key does not exist. (Service: S3, Status Code: 404, Request ID: R71DDHX4XXM0434T, Extended Request ID: d9M/HWvPvMFdPhB6KX+wYCW3ZFqeFo9EoscWPkulOXWa+TnovAE5PlemtuVzKXjlC+rrgskXAus=)"
}
},
"status": 404
}
```
恢复索引快照
<br /> POST _snapshot/my_repository/my_snapshot_2099.05.06/_restore<br /> {<br /> "indices": "my-index,logs-my_app-default",<br /> }<br />
各个集群的还原
- 查看所有注册的存储库:
- node.name=es01
- Elasticsearch 7.10.2 的快照可以还原到 Easysearch 和 Amazon OpenSearch
- 从 Easysearch 1.8.2 还原到 Elasticsearch 7.10.2 报错如下:
json<br /> {<br /> "error": {<br /> "root_cause": [<br /> {<br /> "type": "snapshot_restore_exception",<br /> "reason": "[s3_repository:1/a2qV4NYIReqvgW6BX_nxxw] cannot restore index [my_indexs] because it cannot be upgraded"<br /> }<br /> ],<br /> "type": "snapshot_restore_exception",<br /> "reason": "[s3_repository:1/a2qV4NYIReqvgW6BX_nxxw] cannot restore index [my_indexs] because it cannot be upgraded",<br /> "caused_by": {<br /> "type": "illegal_state_exception",<br /> "reason": "The index [[my_indexs/ALlTCIr0RJqtP06ouQmf0g]] was created with version [1.8.2] but the minimum compatible version is [6.0.0-beta1]. It should be re-indexed in Elasticsearch 6.x before upgrading to 7.10.2."<br /> }<br /> },<br /> "status": 500<br /> }<br />
- 从 Amazon OpenSearch 2.1.3 还原到 Elasticsearch 7.10.2 报错如下(无论是否开启兼容模式):
json<br /> {<br /> "error": {<br /> "root_cause": [<br /> {<br /> "type": "snapshot_restore_exception",<br /> "reason": "[aos:2/D-oyYSscSdCbZFcmPZa_yg] the snapshot was created with Elasticsearch version [36.34.78-beta2] which is higher than the version of this node [7.10.2]"<br /> }<br /> ],<br /> "type": "snapshot_restore_exception",<br /> "reason": "[aos:2/D-oyYSscSdCbZFcmPZa_yg] the snapshot was created with Elasticsearch version [36.34.78-beta2] which is higher than the version of this node [7.10.2]"<br /> },<br /> "status": 500<br /> }<br />
- 从 Easysearch 1.8.2 还原到 Amazon OpenSearch2.13 报错如下(无论是否开启兼容模式):
json<br /> {<br /> "error": {<br /> "root_cause": [<br /> {<br /> "type": "snapshot_restore_exception",<br /> "reason": "[easy_repository:2/LE18AWHlRJu9rpz9BJatUQ] cannot restore index [my_indexs] because it cannot be upgraded"<br /> }<br /> ],<br /> "type": "snapshot_restore_exception",<br /> "reason": "[easy_repository:2/LE18AWHlRJu9rpz9BJatUQ] cannot restore index [my_indexs] because it cannot be upgraded",<br /> "caused_by": {<br /> "type": "illegal_state_exception",<br /> "reason": "The index [[my_indexs/VHOo7yfDTRa48uhQvquFzQ]] was created with version [1.8.2] but the minimum compatible version is OpenSearch 1.0.0 (or Elasticsearch 7.0.0). It should be re-indexed in OpenSearch 1.x (or Elasticsearch 7.x) before upgrading to 2.13.0."<br /> }<br /> },<br /> "status": 500<br /> }<br />
- Amazon OpenSearch 还原到 Easysearch 同样失败
json<br /> {<br /> "error": {<br /> "root_cause": [<br /> {<br /> "type": "snapshot_restore_exception",<br /> "reason": "[aoss:2/D-oyYSscSdCbZFcmPZa_yg] cannot restore index [aos] because it cannot be upgraded"<br /> }<br /> ],<br /> "type": "snapshot_restore_exception",<br /> "reason": "[aoss:2/D-oyYSscSdCbZFcmPZa_yg] cannot restore index [aos] because it cannot be upgraded",<br /> "caused_by": {<br /> "type": "illegal_state_exception",<br /> "reason": "The index [[aos/864WjTAXQCaxJ829V5ktaw]] was created with version [36.34.78-beta2] but the minimum compatible version is [6.0.0]. It should be re-indexed in Easysearch 6.x before upgrading to 1.8.2."<br /> }<br /> },<br /> "status": 500<br /> }<br />
- Elasticsearch 8.14.3 迁移到 Amazon OpenSearch 或者 Elasticsearch 都是有这个报错:
json<br /> {<br /> "error": {<br /> "root_cause": [<br /> {<br /> "type": "parsing_exception",<br /> "reason": "Failed to parse object: unknown field [uuid] found",<br /> "line": 1,<br /> "col": 25<br /> }<br /> ],<br /> "type": "repository_exception",<br /> "reason": "[snap] Unexpected exception when loading repository data",<br /> "caused_by": {<br /> "type": "parsing_exception",<br /> "reason": "Failed to parse object: unknown field [uuid] found",<br /> "line": 1,<br /> "col": 25<br /> }<br /> },<br /> "status": 500<br /> }<br />
这是由于 Elasticsearch 8 在创建快照的时候会默认加上一个 UUID 的字段,所以我们低版本的 Easysearch、Amazon OpenSearch 中会找不到这个字段,在执行GET _cat/snapshots/snap?v
的时候就报错,及时在注册存储库的时候显示加上 UUID 的字段也无事无补。
json<br /> {<br /> "snapshot-repo-name": {<br /> "type": "s3",<br /> "uuid": "qlJ0uqErRmW6aww2Fyt4Fg",<br /> "settings": {<br /> "bucket": "<bucket-name>",<br /> "base_path": "<bucket-prefix>",<br /> }<br /> },<br />
以下是兼容性对比,每行第一列代表源集群,第一行代表目标集群:
| 快照兼容对比 | Easysearch 1.8.2 | Elasticsearch 7.10.2 | OpenSearch 2.13 |
| -------------------- | ---------------- | -------------------- | --------------- |
| Easysearch 1.8.2 | 兼容 | 不兼容 | 不兼容 |
| Elasticsearch 7.10.2 | 兼容 | 兼容 | 兼容 |
| OpenSearch 2.13 | 不兼容 | 不兼容 | 兼容 |
Elasticsearch 的兼容列表官方的列表如下:

参考文献
- 开始使用 Elastic Stack 和 Docker Compose:第 1 部分
https://www.elastic.co/cn/blog ... mpose
- Docker Compose 部署多节点 Elasticsearch
https://www.elastic.co/guide/e ... -file
- repository-s3 教程
https://www.elastic.co/guide/e ... .html
https://www.elastic.co/guide/e ... .html
- snapshot-restore
https://www.elastic.co/guide/e ... .html
- 在亚马逊 OpenSearch 服务中创建索引快照
https://docs.amazonaws.cn/zh_c ... store
- 教程:迁移至 Amazon OpenSearch Service
https://docs.amazonaws.cn/zh_c ... .html
关于 Easysearch 有奖征文活动

无论你是 Easysearch 的老用户,还是第一次听说这个名字,只要你对 INFINI Labs 旗下的 Easysearch 产品感兴趣,或者是希望了解 Easysearch,都可以参加这次活动。
详情查看:[Easysearch 征文活动](/https://infinilabs.cn/blog/202 ... ukong/)
作者:韩旭,亚马逊云技术支持,亚马逊云科技技领云博主,目前专注于云计算开发和大数据领域。
原文:https://infinilabs.cn/blog/202 ... arch/
使用 Easysearch 打造企业内部知识问答系统
INFINI Labs 小助手 发表了文章 • 0 个评论 • 3136 次浏览 • 2024-07-29 11:08
大家可能都有这样的经历,刚入职一家企业时,同事往往会给你分享一些文档资料,有可能是产品信息、规章制度等等。这些文档有的过于冗长,很难第一时间找到想要的内容。有的已经有了新版本,但员工使用的还是老版本。
基于这种背景,我们可以利用 Easysearch 加 LLM 实现一个内部知识的 QA 问答系统。这个系统将利用 LangChain 框架调用本地部署的大模型和 Easysearch,实现理解员工的提问,并基于最新的文档,给出精准答案。
开发框架

整个框架分为四个部分:
- 数据源:数据可以有很多种,可以是非结构化的,比如 PDF、docx、txt 等。也可以是结构化的数据,甚至代码也行。在本次示例中,我们使用 PDF 的非结构化数据。
- 大模型应用:应用与大模型交互,生成我们需要的答案。
- 大模型:系统执行相关任务需要用到的大模型,可以有多个。
- Q&A 场景:基于大模型为引擎的 QA 场景,使用 web 框架,构建一个交互界面。
数据准备
本次我们使用的资料是 "INFINI 产品安装手册.pdf" ,文档部分内容展示如下:

首先我们使用 LangChain 的 document_loaders 来加载文件。document_loaders 集成了数百种数据源格式,可以很方便的加载数据。我们的数据的 pdf 格式的,导入 PyPDFLoader 类来进行处理。代码如下:
```python
import os
导入 Document Loaders
from langchain_community.document_loaders import PyPDFLoader
Load Pdf
base_dir = '.\easysearch' # 文档的存放目录
docs = []
for file in os.listdir(base_dir):
file_path = os.path.join(base_dir, file)
if file.endswith('.pdf'):
loader = PyPDFLoader(file_path)
documents.extend(loader.load())
```
上面的代码将 pdf 文件的内容存储在 docs 这个列表中,以便后续进行处理。
文本分割
一个文件的文本内容可能很大,无法适应许多模型的上下文窗口,也不利于检索和存储。因此,通常我们会将文本内容分割成更小的块,这将帮助我们在运行时只检索文档中最相关的部分。LangChain 提供了工具来进行处理文本分割,非常方便。
我们将把文档分割成 1000 个字符的块,每个块之间有 200 个重叠字符。这种重叠有助于减少将语句与相关的重要上下文分离的可能性。
```python2.将Documents切分成块
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=20)
chunked_documents = text_splitter.split_documents(docs)
```
上面的代码将 docs 的内容按 1000 字符大小进行切分,存储在 chunked_documents 中,以便后续进行处理。
注意,实际运行中,切分及重叠的大小,都会影响应用效果,需自行调试。
向量库 Easysearch
接下来,我们将这些文本块转换成向量的形式,并存储在一个向量数据库中。在本示例中,我们使用 mxbai-embed-large 模型来生成向量,然后将向量和原始内容存入 easysearch 。
本地部署模型,我使用的是 ollama ,大家可以使用自己喜欢的工具。
```python3. 定义embedding模型
from langchain_community.embeddings import OllamaEmbeddings
ollama_emb = OllamaEmbeddings(
model="mxbai-embed-large",
)
4. 定义 easysearch 集群的信息,以及存放向量的索引名称 infini
from langchain_community.vectorstores import EcloudESVectorStore
ES_URL = "<a href="https://192.168.56.3:9200"" rel="nofollow" target="_blank">https://192.168.56.3:9200"
USER = "admin"
PASSWORD = "e5ac1b537785ae27c187"
indexname = "infini"
docsearch = EcloudESVectorStore.from_documents(
chunked_documents,
ollama_emb,
es_url=ES_URL,
user=USER,
password=PASSWORD,
index_name=indexname,
verify_certs=False,
)
```
通过上面的步骤,我们成功将文本块转换成了向量,并存入到了 easysearch 集群的 infini 索引中。

我们看看 infini 索引内容是怎样的

text 字段存放了文本块的原始内容,vector 字段存放着对应的向量表示。
检索及生成答案
在这一步,我们会定义一个生成式大模型。然后创建一个 RetrievalQA 链,它是一个检索式问答模型,用于生成问题的答案。
在 RetrievalQA 链中有下面两大重要组成部分。
- LLM 是大模型,负责回答问题。
- retriever(vectorstore.as_retriever())负责根据用户的问题检索相关的信息。先是找最近似的“向量块”,再把”向量块“对应的“文档块”作为知识信息,和问题一起传递进入大模型。之所以要先检索,是因为从互联网信息训练而来的大模型不可能拥有一个私营企业的内部知识。
```python
5. Retrieval 准备模型和Retrieval链
import logging
MultiQueryRetriever工具
from langchain.retrievers.multi_query import MultiQueryRetriever
RetrievalQA链
from langchain.chains import RetrievalQA
设置Logging
logging.basicConfig()
logging.getLogger('langchain.retrievers.multi_query').setLevel(logging.INFO)
实例化一个大模型工具
from langchain_community.chat_models import ChatOllama
llm = ChatOllama(model="qwen2:latest")
from langchain.prompts import PromptTemplate
my_template = PromptTemplate(
input_variables=["question"],
template="""You are an AI language model assistant. Your task is
to generate 3 different versions of the given user
question in Chinese to retrieve relevant documents from a vector database.
By generating multiple perspectives on the user question,
your goal is to help the user overcome some of the limitations
of distance-based similarity search. Provide these alternative
questions separated by newlines. Original question: {question}""",
)
实例化一个MultiQueryRetriever
retriever_from_llm = MultiQueryRetriever.from_llm(retriever=docsearch.as_retriever(), llm=llm,prompt=my_template,include_original=True)
实例化一个RetrievalQA链
qa_chain = RetrievalQA.from_chain_type(llm,retriever=retriever_from_llm)
``<br /> <br /> 这里我们使用 ollama 在本地部署一个 qwen2 大模型,负责问题改写和生成答案。<br /> <br /> 启动 qwen2 大模型:
ollama run qwen2`

我们获取到用户问题后,先通过 MultiQueryRetriever 类调用大模型 qwen2 进行改写,生成 3 个同样语义的问题,然后再调用 easyearch 进行向量检索,搜索相关内容。
最后把所有相关内容,合并、去重后,与原始问题一起提交给大模型 qwen2,进行答案生成。
虽然这里使用的是向量检索,但实际上我们可以同时使用全文检索和向量检索。这也是使用 easysearch 作为检索库的优势之一。
前端展示
这一步我们创建一个 Flask 应用(需要安装 Flask 包)来接收用户的问题,并生成相应的答案,最后通过 index.html 对答案进行渲染和呈现。
在这个步骤中,我们使用了之前创建的 RetrievalQA 链来获取相关的文档和生成答案。然后,将这些信息返回给用户,显示在网页上。
```python6. Q&A系统的UI实现
from flask import Flask, request, render_template
app = Flask(name) # Flask APP
@app.route('/', methods=['GET', 'POST'])
def home():
if request.method == 'POST':
接收用户输入作为问题
question = request.form.get('question')<br />
RetrievalQA链 - 读入问题,生成答案
result = qa_chain({"query": question})<br />
把大模型的回答结果返回网页进行渲染
return render_template('index.html', result=result)<br />
return render_template('index.html')
if name == "main":
app.run(host='0.0.0.0',debug=True,port=5000)
```
效果演示
我们模仿用户进行提问。

Q&A 系统进行回答,回答速度取决于本地的计算资源。

内容校验,在原始文档内用 ctrl+F 搜索关键字 LOGGING_ES_ENDPOINT 得到如下内容。

嗯,回答的还不错,达到预期目的。如果还有其他要求,可修改 my_template 中的提示词或者替换成别的大模型也是可以的。
小结
通过这次示例,我们演示了如何基于 LangChain 和 easysearch 以及大模型,快速开发出一个内部知识问答系统。怎么样,是不是觉得整个流程特别简单易懂?
如有任何问题,请随时联系我,期待与您交流!

关于 Easysearch 有奖征文活动

无论你是 Easysearch 的老用户,还是第一次听说这个名字,只要你对 INFINI Labs 旗下的 Easysearch 产品感兴趣,或者是希望了解 Easysearch,都可以参加这次活动。
详情查看:[Easysearch 征文活动](https://infinilabs.cn/blog/202 ... ukong/)
Easysearch 新特性:写入限流功能介绍
INFINI Labs 小助手 发表了文章 • 0 个评论 • 3361 次浏览 • 2024-07-17 14:52
背景
在 Easysearch 的各种使用场景中,高写入吞吐量的场景占了很大一部分,由此也带来了一些使用上的问题,很多用户由于使用经验不足,对集群的写入压测进行的不够充分,不能很好的规划集群的写入量。
导致经常发生以下问题:
- 写入吞吐量过大对内存影响巨大,引发节点 OOM,节点掉线问题。
- 对 CPU 和内存的占用严重影响了其他的查询业务的响应。
- 以及磁盘 IO 负载增加,挤占集群的网络带宽等问题。
之前就有某金融保险类客户遇到了因业务端写入量突然猛增导致数据节点不停的 Full GC,进而掉入了不停的掉线,上线,又掉线的恶性循环中。当时只能建议用户增加一个类似“挡板”的服务,在数据进入到集群之前进行拦截,对客户端写入进行干预限流:

这样做虽然有效,但是也增加了整个系统的部署复杂性,提高了运维成本。
根据客户的实际场景,Easysearch 从 1.8.0 版本开始引入了节点和 Shard 级别的限流功能,不用依赖第三方就可以限制写入压力,并在 1.8.2 版本增加了索引级别的写入限流。
注意:所有写入限流都是针对各数据节点的 Primary Shard 写入进行限流的,算上副本的话吞吐量要乘以 2。
限流示意图:

下面是限流前后相同数据节点的吞吐量和 CPU 对比:
测试环境:
<br /> ip name http port version role master<br /> 10.0.0.3 node-3 10.0.0.3:9209 9303 1.8.0 dimr -<br /> 10.0.0.3 node-4 10.0.0.3:9210 9304 1.8.0 im -<br /> 10.0.0.3 node-2 10.0.0.3:9208 9302 1.8.0 dimr -<br /> 10.0.0.3 node-1 10.0.0.3:9207 9301 1.8.0 dimr *<br />
测试索引配置:
<br /> PUT test_0<br /> {<br /> "settings": {<br /> "number_of_replicas": 1,<br /> "number_of_shards": 3<br /> }<br /> }<br />
压测工具:采用极限科技的 [INFINI Loadgen](https://infinilabs.cn/docs/lat ... hmark/) 压测,这款压测工具使用简单,可以方便对任何支持 Rest 接口的库进行压测。
压测命令:
bash<br /> ./loadgen-linux-amd64 -d 180 -c 10 -config loadgen-easy-1.8.yml<br />
压测 180 秒,10 个并发,每个 bulk 请求 5000 条。
节点级别限流
通过 [INFINI Console](https://infinilabs.cn/products/console/) 监控指标可以看到,限流之前的某个数据节点,CPU 占用 10%,每秒写入 40000 条左右:

在 Cluster Settings 里配置,启用节点级别限流,限制每个节点的每秒最大写入 10000 条,并在默认的 1 秒间隔内进行重试,超过默认间隔后直接拒绝。
<br /> PUT _cluster/settings<br /> {<br /> "transient": {<br /> "cluster.throttle.node.write": true,<br /> "cluster.throttle.node.write.max_requests": 10000,<br /> "cluster.throttle.node.write.action": "retry"<br /> }<br /> }<br />
限流后,CPU 占用降低了约 50%,算上副本一共 20000 条每秒:

Shard 级别限流
设置每个分片最大写入条数为 2000 条每秒
<br /> PUT _cluster/settings<br /> {<br /> "transient": {<br /> "cluster.throttle.shard.write": true,<br /> "cluster.throttle.shard.write.max_requests": 2000,<br /> "cluster.throttle.shard.write.action": "retry"<br /> }<br /> }<br />
集群级别的监控,同样是只针对主 Shard。

从 Console 的监控指标可以看出,索引 test_0 的 Primary indexing 维持在 6000 左右,正好是 3 个主分片限制的 2000 的写入之和。

再看下数据节点监控,Total Shards 表示主分片和副本分片的写入总和即 4000,单看主分片的话,正好是 2000.

索引级别限流
有时,集群中可能某个索引的写入吞吐过大而影响了其他业务,也可以针对特定的索引配置写入限制。
可以在索引的 Settings 里设置当前索引每秒写入最大条数为 6000:
<br /> PUT test_0<br /> {<br /> "settings": {<br /> "number_of_replicas": 1,<br /> "number_of_shards": 3,<br /> "index.throttle.write.max_requests": 6000,<br /> "index.throttle.write.action": "retry",<br /> "index.throttle.write.enable": true<br /> }<br /> }<br />
下图索引的 Primary indexing 在 6000 左右,表示索引的所有主分片的写入速度限制在了 6000。

总结
通过本次测试对比,可以看出限流的好处:
- 有效控制写入压力:
写入限流功能能够有效限制每个节点和每个 Shard 的写入吞吐量,防止因写入量过大而导致系统资源被过度消耗的问题。
- 降低系统资源占用:
在限流前,某数据节点的 CPU 占用率约为 10%。限流后,CPU 占用率显著降低至约 5%,减少了约 50%。这表明在高并发写入场景下,写入限流功能显著降低了系统的 CPU 负载。
- 提高系统稳定性:
通过控制写入吞吐量,避免了频繁的 Full GC 和节点掉线问题,从而提升了系统的整体稳定性和可靠性。
- 保障查询业务性能:
写入限流功能减少了写入操作对 CPU 和内存的占用,确保其他查询业务的响应性能不受影响。
综上所述,写入限流功能在高并发写入场景下表现出色,不仅有效控制了写入压力,还显著降低了系统资源占用,从而提高了系统的稳定性和查询业务的性能。
关于 Easysearch 有奖征文活动

无论你是 Easysearch 的老用户,还是第一次听说这个名字,只要你对 INFINI Labs 旗下的 Easysearch 产品感兴趣,或者是希望了解 Easysearch,都可以参加这次活动。
详情查看:[Easysearch 征文活动](https://infinilabs.cn/blog/202 ... ukong/)
作者:张磊
原文:https://infinilabs.cn/blog/202 ... tion/
- 有效控制写入压力:
玩转 Easysearch 语法
INFINI Labs 小助手 发表了文章 • 0 个评论 • 4401 次浏览 • 2024-07-11 12:11

什么是 Easysearch
Elasticsearch 是一个基于 Apache Lucene 的开源分布式搜索和分析引擎,它被广泛应用于全文搜索、结构化搜索和分析等多种场景中。作为 Elasticsearch 的国产化替代方案,Easysearch 不仅保持了与原生 Elasticsearch 的高度兼容性,还在功能、性能、稳定性和扩展性方面进行了全面提升。对于开发团队来说,从 Elasticsearch 切换到 Easysearch 不需要做任何业务代码的调整,确保了无缝衔接和平滑迁移。
Easysearch 是基于 Elasticsearch 7.10.2 开源版本二次开发,所以支持 Elasticsearch 原始的 Query DSL 语法,基本的 SQL 语法,并且兼容现有 Elasticsearch 的 SDK,使得应用无需修改代码即可进行迁移。其平滑的迁移特性,如基于网关的无缝跨版本迁移与升级,提供了随时安全回退的能力。
在之前的文章中,我们已经介绍了 [Easysearch 的搭建](https://infinilabs.cn/blog/202 ... ds-on/) 和 [可视化工具的使用](https://infinilabs.cn/blog/202 ... guide/),今天我们将探讨 Easysearch 集群的基本概念和常用的 API。
Easysearch 集群的核心概念
Easysearch 集群由以下几个核心概念构成:
- 节点(Node):集群中的单个服务器,负责存储数据并参与集群的索引和搜索功能。
- 集群(Cluster):由一个或多个节点组成,拥有唯一的集群名,协同完成数据索引和查询任务。
- 索引(Index):存储相关数据的容器,类似于关系数据库中的数据库,一个索引包含多个文档。
- 文档(Document):索引中的基本数据单位,相当于关系数据库中的行。
- 字段(Field):文档中的一个属性,相当于数据库中的列。
- 分片(Shard):为了提高性能和扩展性,索引可以被分割成多个分片,每个分片是索引的一个部分。
- 副本(Replica):分片的副本,用于提高数据的可靠性和在节点出现故障时的可用性。
通过多个 API,例如_cluster/health
和_cluster/stats
,用户可以轻松查看集群的健康状态和详细信息,这些信息对于维护和优化 Easysearch 集群至关重要。
无论是在性能的提升,还是在功能的兼容性方面,Easysearch 都为用户提供了一个强大的搜索引擎平台,让从 Elasticsearch 到 Easysearch 的迁移变得无缝且高效。掌握其核心概念和 API 的使用,将帮助开发者更好地利用这些工具来构建和优化他们的搜索解决方案。

查看集群信息
在 Easysearch 中,可以通过多个 API 来查看集群的各种信息,包括集群的健康状况、节点信息和索引状态。以下是一些常用的查看集群信息的 API 和示例:
查看集群健康状况
_cluster/health
API 可以查看集群的健康状态,包括集群是否处于正常状态、节点数量、分片状态等。
<br /> GET /_cluster/health<br />
示例响应:
json<br /> {<br /> "cluster_name": "my_cluster",<br /> "status": "green",<br /> "timed_out": false,<br /> "number_of_nodes": 3,<br /> "number_of_data_nodes": 3,<br /> "active_primary_shards": 5,<br /> "active_shards": 10,<br /> "relocating_shards": 0,<br /> "initializing_shards": 0,<br /> "unassigned_shards": 0,<br /> "delayed_unassigned_shards": 0,<br /> "number_of_pending_tasks": 0,<br /> "number_of_in_flight_fetch": 0,<br /> "task_max_waiting_in_queue_millis": 0,<br /> "active_shards_percent_as_number": 100.0<br /> }<br />
查看集群状态
_cluster/stats
API 可以查看集群的详细状态,包括索引、节点、分片等信息。
<br /> GET /_cluster/stats<br />
示例响应:
json<br /> {<br /> "cluster_name": "my_cluster",<br /> "status": "green",<br /> "indices": {<br /> "count": 10,<br /> "shards": {<br /> "total": 20,<br /> "primaries": 10,<br /> "replication": 1.0,<br /> "index": {<br /> "shards": {<br /> "min": 1,<br /> "max": 5,<br /> "avg": 2.0<br /> }<br /> }<br /> }<br /> },<br /> "nodes": {<br /> "count": {<br /> "total": 3,<br /> "data": 3,<br /> "coordinating_only": 0,<br /> "master": 1,<br /> "ingest": 2<br /> },<br /> "os": {<br /> "available_processors": 12,<br /> "allocated_processors": 12<br /> },<br /> "process": {<br /> "cpu": {<br /> "percent": 10<br /> },<br /> "open_file_descriptors": {<br /> "min": 100,<br /> "max": 300,<br /> "avg": 200<br /> }<br /> }<br /> }<br /> }<br />
查看节点信息
_nodes
API 可以查看集群中节点的详细信息,包括节点角色、IP 地址、内存使用情况等。
<br /> GET /_nodes<br />
示例响应:
json<br /> {<br /> "cluster_name": "my_cluster",<br /> "nodes": {<br /> "node_id_1": {<br /> "name": "node_1",<br /> "transport_address": "192.168.1.1:9300",<br /> "host": "192.168.1.1",<br /> "ip": "192.168.1.1",<br /> "roles": ["master", "data", "ingest"],<br /> "os": {<br /> "available_processors": 4,<br /> "allocated_processors": 4<br /> },<br /> "process": {<br /> "cpu": {<br /> "percent": 10<br /> },<br /> "open_file_descriptors": 200<br /> }<br /> },<br /> "node_id_2": {<br /> "name": "node_2",<br /> "transport_address": "192.168.1.2:9300",<br /> "host": "192.168.1.2",<br /> "ip": "192.168.1.2",<br /> "roles": ["data"],<br /> "os": {<br /> "available_processors": 4,<br /> "allocated_processors": 4<br /> },<br /> "process": {<br /> "cpu": {<br /> "percent": 15<br /> },<br /> "open_file_descriptors": 150<br /> }<br /> }<br /> }<br /> }<br />
查看索引状态
_cat/indices
API 可以查看集群中所有索引的状态,包括文档数、存储大小、分片数等信息。
<br /> GET /_cat/indices?v<br />
示例响应:
<br /> health status index uuid pri rep docs.count docs.deleted store.size pri.store.size<br /> green open index_1 SxNUd84vRl6QH5P7g0T4Vg 1 1 0 0 230b 230b<br /> green open index_2 NxEYib4yToCnA1PpQ8P4Xw 5 1 100 1 10mb 5mb<br />
这些 API 可以帮助你全面了解 Easysearch 集群的状态和健康状况,从而更好地管理和维护集群。

增删改查操作
在 Easysearch 中,增删改查操作是管理数据和索引的基本功能。以下是如何使用这些操作的详细示例。
创建索引
创建一个新的索引,并指定分片和副本的数量:
<br /> PUT /my_index<br /> {<br /> "settings": {<br /> "number_of_shards": 3,<br /> "number_of_replicas": 2<br /> }<br /> }<br />
删除索引
删除一个不再需要的索引:
<br /> DELETE /my_index<br />
添加文档
通过 POST 或 PUT 请求向索引中添加文档:
<br /> POST /my_index/_doc/1<br /> {<br /> "name": "John Doe",<br /> "age": 30,<br /> "occupation": "Engineer"<br /> }<br />
<br /> PUT /my_index/_doc/1<br /> {<br /> "name": "John Doe",<br /> "age": 30,<br /> "occupation": "Engineer"<br /> }<br />

POST
和PUT
方法用于不同的操作,尽管它们都可以用于添加或更新文档,但它们的行为有所不同。
POST /my_index/_doc/1
方法用于创建或替换一个文档。如果指定的文档 ID 已经存在,POST
请求将更新整个文档(不会合并字段)。如果文档 ID 不存在,它将创建一个新的文档。
<br /> <br /> POST /my_index/_doc/1<br /> {<br /> "name": "John Doe",<br /> "age": 30,<br /> "occupation": "Engineer"<br /> }<br />
PUT /my_index/_doc/1
方法通常用于创建一个新的文档,或者完全替换一个已存在的文档。与POST
类似,如果指定的文档 ID 已经存在,PUT
请求将替换整个文档。
<br /> PUT /my_index/_doc/1<br /> {<br /> "name": "John Doe",<br /> "age": 30,<br /> "occupation": "Engineer"<br /> }<br />
1.使用场景:
POST
:更适合用于添加或部分更新文档,即使文档 ID 已经存在。PUT
:更适合用于创建或完全替换文档。
2.ID 自动生成:
POST
请求可以不提供文档 ID,此时 Easysearch 会自动生成一个文档 ID。PUT
请求必须提供文档 ID,如果未提供,则会返回错误。
3.部分更新:
POST
请求可以用于部分更新(通过_update
API)。PUT
请求用于完全替换文档,不支持部分更新。
如果文档 ID 已经存在,POST
和PUT
都会覆盖整个文档,并且效果是一样的。但是,通常POST
用于提交数据,而PUT
用于上传和替换资源。
1.使用POST
方法添加或更新文档:
<br /> POST /my_index/_doc/1<br /> {<br /> "name": "John Doe",<br /> "age": 30,<br /> "occupation": "Engineer"<br /> }<br />
2.使用PUT
方法添加或更新文档:
<br /> PUT /my_index/_doc/1<br /> {<br /> "name": "John Doe",<br /> "age": 30,<br /> "occupation": "Engineer"<br /> }<br />
在这两个示例中,结果都是在索引my_index
中创建或更新文档 ID 为1
的文档。无论使用POST
还是 PUT,如果文档 ID 已存在,都会覆盖原有的文档内容。
新建文档
使用_create
方法新建文档,如果文档已经存在则返回错误:
<br /> PUT /my_index/_create/1<br /> {<br /> "a": 1<br /> }<br />
如果尝试新建已存在的文档,将会出现如下错误:
json<br /> {<br /> "error": {<br /> "root_cause": [<br /> {<br /> "type": "version_conflict_engine_exception",<br /> "reason": "[1]: version conflict, document already exists (current version [1])",<br /> "index_uuid": "1xWdHLTaTm6l6HbqACaIEA",<br /> "shard": "0",<br /> "index": "my_index"<br /> }<br /> ],<br /> "type": "version_conflict_engine_exception",<br /> "reason": "[1]: version conflict, document already exists (current version [1])",<br /> "index_uuid": "1xWdHLTaTm6l6HbqACaIEA",<br /> "shard": "0",<br /> "index": "my_index"<br /> },<br /> "status": 409<br /> }<br />
获取文档
通过 ID 获取文档的详细信息:
<br /> GET /my_index/_doc/1<br />
更新文档
更新文档的特定字段,保留原有字段:
<br /> POST /my_index/_update/1<br /> {<br /> "doc": {<br /> "age": 31<br /> }<br /> }<br />
删除文档
通过 ID 删除指定的文档:
<br /> DELETE /my_index/_doc/1<br />
查询所有文档
查询索引中的所有文档:
<br /> GET /my_index/_search<br /> {<br /> "query": {<br /> "match_all": {}<br /> }<br /> }<br />
这个是 [《老杨玩搜索》](https://space.bilibili.com/1171585214/video)中总结的图,可以作为“小抄”来记忆:

批量操作 (_bulk API)
_bulk API
用于在一次请求中执行多个索引、删除和更新操作,这对于批量处理大规模数据非常有用,可以显著提高性能和效率。以下是_bulk API
的基本使用示例:
<br /> POST /my_index/_bulk<br /> { "index": { "_id": "1" } }<br /> { "name": "John Doe", "age": 30, "occupation": "Engineer" }<br /> { "index": { "_id": "2" } }<br /> { "name": "Jane Doe", "age": 25, "occupation": "Designer" }<br /> { "update": { "_id": "1" } }<br /> { "doc": { "age": 31 } }<br />

_bulk API
的请求体由多个操作和文档组成。每个操作行包含一个动作描述行和一个可选的源文档行。动作描述行指明了操作的类型(例如,index、create、delete、update)以及操作的元数据。源文档行则包含了实际的数据。
每个操作之间需要用换行符分隔,并且请求体最后必须以换行符结尾。
<br /> POST /_bulk<br /> { "index": { "_index": "a", "_id": "1" } }<br /> { "name": "John Doe", "age": 30, "occupation": "Engineer" }<br /> { "index": { "_index": "b", "_id": "2" } }<br /> { "name": "Jane Doe", "age": 25, "occupation": "Designer" }<br /> { "update": { "_index": "a", "_id": "1" } }<br /> { "doc": { "age": 31 } }<br />

分词器
在 Easysearch 中,分词器(Analyzer)用于将文本分解为词项(terms),是全文搜索和文本分析的基础。分词器通常由字符过滤器(Character Filters)、分词器(Tokenizer)和词项过滤器(Token Filters)组成。以下是关于分词器的详细介绍:
1.字符过滤器(Character Filters):在分词之前对文本进行预处理。例如,去除 HTML 标签,替换字符等。
2.分词器(Tokenizer):将文本分解为词项(tokens)。这是分词过程的核心。
3.词项过滤器(Token Filters):对词项进行处理,如小写化、去除停用词、词干提取等。

只有 text 字段支持全文检索,返回的结果根据相似度打分,我们一起看下
<br /> POST /index/_mapping<br /> {<br /> "properties": {<br /> "content": {<br /> "type": "text",<br /> "analyzer": "ik_max_word",<br /> "search_analyzer": "ik_smart"<br /> }<br /> }<br /> }<br />
.POST /index/_mapping
- 这个部分表示要向名为
index
的索引添加或更新映射设置。
2.“properties”
properties
定义了索引中文档的字段结构。在这个例子中,定义了一个名为content
的字段。
3.“content”
- 定义了名为
content
的字段。
4.“type”: “text”
type
字段指定content
字段的数据类型为text
。text
类型适用于需要分词和全文搜索的字段。
5.“analyzer”: “ik_max_word”
analyzer
字段指定索引时使用的分词器为ik_max_word
。ik_max_word
是 IK 分词器中的一种,它会尽可能多地将文本分解为更多的词项。
6.“search_analyzer”: “ik_smart”
search_analyzer
字段指定搜索时使用的分词器为ik_smart
。ik_smart
是 IK 分词器中的另一种,它会更智能地进行分词,以提高搜索的准确性。
当然,在设置这个 mapping 的时候可以使用同样的分词器,也可以使用不同的分词器。这里介绍下 IK 分词器:
- IK 分词器是一种中文分词器,适用于中文文本的分词。IK 分词器有两种分词模式:
ik_max_word
和ik_smart
。 ik_max_word
:将文本尽可能多地切分成词项,适用于需要更高召回率的场景。ik_smart
:进行最智能的分词,适用于需要更高精度的搜索场景。
这个 DSL 的设置意味着,在向这个索引添加或更新文档时,content
字段的文本会使用ik_max_word
分词器进行分词处理,以确保文本被尽可能多地切分成词项。而在搜索时,content
字段的文本会使用ik_smart
分词器进行分词处理,以提高搜索的准确性和相关性。
以下是关于 standard,ik_smart,ik_max_word 这几个分词器的对比:
<br /> GET /_analyze<br /> {<br /> "tokenizer": "standard",<br /> "text": "我,机器人"<br /> }<br /> <br /> GET /_analyze<br /> {<br /> "tokenizer": "ik_smart",<br /> "text": "我,机器人"<br /> }<br /> <br /> GET /_analyze<br /> {<br /> "tokenizer": "ik_max_word",<br /> "text": "我,机器人"<br /> }<br />
结果如下:
```
GET /_analyze (standard)
{
"tokens": [
{
"token": "我",
"start_offset": 0,
"end_offset": 1,
"type": "",
"position": 0
},
{
"token": "机",
"start_offset": 2,
"end_offset": 3,
"type": "",
"position": 1
},
{
"token": "器",
"start_offset": 3,
"end_offset": 4,
"type": "",
"position": 2
},
{
"token": "人",
"start_offset": 4,
"end_offset": 5,
"type": "",
"position": 3
}
]
}GET /_analyze(ik_smart)
{
"tokens": [
{
"token": "我",
"start_offset": 0,
"end_offset": 1,
"type": "CN_CHAR",
"position": 0
},
{
"token": "机器人",
"start_offset": 2,
"end_offset": 5,
"type": "CN_WORD",
"position": 1
}
]
}GET /_analyze (ik_max_word)
{
"tokens": [
{
"token": "我",
"start_offset": 0,
"end_offset": 1,
"type": "CN_CHAR",
"position": 0
},
{
"token": "机器人",
"start_offset": 2,
"end_offset": 5,
"type": "CN_WORD",
"position": 1
},
{
"token": "机器",
"start_offset": 2,
"end_offset": 4,
"type": "CN_WORD",
"position": 2
},
{
"token": "人",
"start_offset": 4,
"end_offset": 5,
"type": "CN_CHAR",
"position": 3
}
]
}
<br /> <br /> <br /> <br /> 如果使用了不存在的分词器会出现这个错误。<br /> <br />
json
{
"error": {
"root_cause": [
{
"type": "illegal_argument_exception",
"reason": "failed to find global tokenizer under [simple]"
}
],
"type": "illegal_argument_exception",
"reason": "failed to find global tokenizer under [simple]"
},
"status": 400
}
```
精确搜索/正则表达式搜索/通配符
在 Easysearch 中,精确搜索、正则表达式搜索和通配符搜索是三种不同的搜索方式,各有其应用场景和特点:
1.精确搜索 (Term Query):
- 精确搜索用于查找与搜索词完全匹配的文档。
- 不进行分词处理,通常用于关键字、ID、标签等字段的精确匹配。
- 适用于结构化数据或不需要分词的字段(如数字、日期、布尔值等)。
json<br /> {<br /> "query": {<br /> "term": {<br /> "status": "active"<br /> }<br /> }<br /> }<br />
2.正则表达式搜索 (Regexp Query):
- 正则表达式搜索用于基于正则表达式模式匹配的文档搜索。
- 支持复杂的字符串匹配模式,但性能可能较低,特别是当数据量较大时。
- 适用于需要灵活且复杂匹配条件的搜索。
json<br /> {<br /> "query": {<br /> "regexp": {<br /> "content": "Easysearch .*powerful"<br /> }<br /> }<br /> }<br />
3.通配符搜索 (Wildcard Query):
- 通配符搜索用于通过通配符模式匹配文档。
- 支持 ?(匹配单个字符)和 *(匹配零个或多个字符)。
- 性能相对较差,因为通配符搜索可能需要扫描大量数据。
json<br /> {<br /> "query": {<br /> "wildcard": {<br /> "username": "john*"<br /> }<br /> }<br /> }<br />
- 精确搜索:用于需要绝对匹配特定词语或不需要分词的字段。例如,查找特定用户 ID 或状态。
- 正则表达式搜索:用于需要复杂字符串模式匹配的场景,但要谨慎使用,避免性能问题。
- 通配符搜索:用于简单模式匹配,但同样需要注意性能影响,尽量避免在大数据集上频繁使用。
接下来看这个例子,我们将使用批量导入数据,然后进行几种不同类型的查询,包括精确查询、通配符查询和正则表达式查询。
<br /> POST /users/_bulk<br /> { "index": { "_index": "users", "_id": 1 }}<br /> { "username": "john_doe", "status": "active", "email": "john.doe@example.com", "bio": "John loves Easysearch and open-source technologies." }<br /> { "index": { "_index": "users", "_id": 2 }}<br /> { "username": "jane_doe", "status": "inactive", "email": "jane.doe@example.com", "bio": "Jane is a data scientist working with big data." }<br /> { "index": { "_index": "users", "_id": 3 }}<br /> { "username": "john_smith", "status": "active", "email": "john.smith@example.com", "bio": "John enjoys hiking and nature." }<br /> { "index": { "_index": "users", "_id": 4 }}<br /> { "username": "alice_jones", "status": "active", "email": "alice.jones@example.com", "bio": "Alice is a software engineer specialized in JavaScript." }<br /> { "index": { "_index": "users", "_id": 5 }}<br /> { "username": "bob_jones", "status": "inactive", "email": "bob.jones@example.com", "bio": "Bob is an AI enthusiast and machine learning expert." }<br />
1.精确查询:查询状态为 “active” 的用户。
<br /> GET /users/_search<br /> {<br /> "query": {<br /> "term": {<br /> "status": "active"<br /> }<br /> }<br /> }<br />
2.通配符查询:查询 bio 字段中包含 “John” 开头的词。
<br /> GET /users/_search<br /> {<br /> "query": {<br /> "wildcard": {<br /> "bio": "John*"<br /> }<br /> }<br /> }<br />
3.正则表达式查询:查询用户名以 “john” 开头的用户
<br /> GET /users/_search<br /> {<br /> "query": {<br /> "regexp": {<br /> "username": "john.*"<br /> }<br /> }<br /> }<br />
通过这些例子,你可以看到如何在 Easysearch 中使用批量导入数据,然后使用各种查询方法来检索特定条件的数据。这些查询方法可以帮助你高效地搜索和分析数据,以满足不同的业务需求。
这里同样是[《老杨玩搜索》](https://space.bilibili.com/1171585214/video)中总结的“小抄”来方便记忆:



多字段查询
在 Easysearch 中,多字段查询允许您在多个字段上同时执行搜索,以获取更精确的结果。最常用的多字段查询类型是multi_match
查询。multi_match
查询是match
查询的扩展,能够在多个字段中搜索指定的关键词。
multi_match
查询支持多种匹配模式,如best_fields
、most_fields
、cross_fields
、phrase
和phrase_prefix
。以下是各模式的简要介绍:
- best_fields:默认模式,选择匹配度最高的字段。
- most_fields:计算每个字段的匹配度,然后将匹配度相加。
- cross_fields:将多个字段视为一个字段进行匹配,适用于分析文本被分散到多个字段的情况。
- phrase:短语匹配,确保词项顺序与查询相同。
- phrase_prefix:短语前缀匹配,允许词项的部分匹配。

我们先导入一些示例数据到一个索引documents
中:
<br /> POST /documents/_bulk<br /> { "index": { "_id": 1 } }<br /> { "title": "Easysearch Guide", "content": "This is an introductory guide to Easysearch ." }<br /> { "index": { "_id": 2 } }<br /> { "title": "Advanced Easysearch ", "content": "This guide covers advanced topics in Easysearch ." }<br /> { "index": { "_id": 3 } }<br /> { "title": "Easysearch in Action", "content": "Practical guide to Easysearch usage." }<br /> { "index": { "_id": 4 } }<br /> { "title": "Learning Easysearch ", "content": "Beginner's guide to learning Easysearch ." }<br />
我们将使用multi_match
查询在title
和content
字段中同时搜索关键词。
1.基本 multi_match 查询:
<br /> POST /documents/_search<br /> {<br /> "query": {<br /> "multi_match": {<br /> "query": "guide",<br /> "fields": ["title", "content"]<br /> }<br /> }<br /> }<br />
2.指定匹配模式为 best_fields:
<br /> POST /documents/_search<br /> {<br /> "query": {<br /> "multi_match": {<br /> "query": "guide",<br /> "fields": ["title", "content"],<br /> "type": "best_fields"<br /> }<br /> }<br /> }<br />
3.指定匹配模式为 most_fields:
<br /> POST /documents/_search<br /> {<br /> "query": {<br /> "multi_match": {<br /> "query": "guide",<br /> "fields": ["title", "content"],<br /> "type": "most_fields"<br /> }<br /> }<br /> }<br />
4.使用 cross_fields 模式:
<br /> POST /documents/_search<br /> {<br /> "query": {<br /> "multi_match": {<br /> "query": "Easysearch guide",<br /> "fields": ["title", "content"],<br /> "type": "cross_fields"<br /> }<br /> }<br /> }<br />
5.短语匹配 (phrase):
<br /> POST /documents/_search<br /> {<br /> "query": {<br /> "multi_match": {<br /> "query": "introductory guide",<br /> "fields": ["title", "content"],<br /> "type": "phrase"<br /> }<br /> }<br /> }<br />
6.短语前缀匹配 (phrase_prefix):
<br /> POST /documents/_search<br /> {<br /> "query": {<br /> "multi_match": {<br /> "query": "introductory gui",<br /> "fields": ["title", "content"],<br /> "type": "phrase_prefix"<br /> }<br /> }<br /> }<br />
- query:要搜索的关键词或短语。
- fields:要搜索的字段列表,可以包含一个或多个字段。
- type:指定匹配模式,默认为 best_fields。
使用multi_match
查询,您可以在多个字段上同时执行搜索,获得更精确和全面的结果。通过指定不同的匹配模式,您可以调整查询行为以满足特定的搜索需求。无论是基本关键词匹配、短语匹配还是跨字段匹配,multi_match
查询都提供了强大的功能来处理复杂的搜索场景。
除此之外,还可以使用 boost 参数用于调整特定字段的权重,从而影响搜索结果的相关性评分。multi_match
查询支持为不同字段设置不同的 boost 值,以便在搜索结果中优先显示某些字段的匹配项。

布尔查询
布尔查询是 Easysearch 中非常强大且灵活的一种查询方式,它允许用户通过组合多个查询条件来实现复杂的搜索需求。布尔查询使用bool
查询类型,可以包含以下几种子句:must
、filter
、must_not
和should
。每种子句都有其特定的用途和语义。
1.must:
- 包含在
must
数组中的查询条件必须匹配,类似于逻辑上的 AND 操作。 - 如果有多个条件,所有条件都必须满足,文档才会被包含在结果集中。
2.filter:
- 包含在
filter
数组中的查询条件必须匹配,但它不会影响评分。 filter
子句通常用于对性能要求较高的过滤操作,因为它不计算相关性评分。
3.must_not:
- 包含在
must_not
数组中的查询条件必须不匹配,类似于逻辑上的 NOT 操作。 - 如果有任何一个条件匹配,文档就会被排除在结果集之外。
4.should:
- 包含在
should
数组中的查询条件至少匹配一个。 - 如果布尔查询中没有
must
子句,则至少要匹配一个should
子句。 should
子句在计算相关性评分时也有影响。
5.minimum_should_match:
- 指定
should
子句中至少需要满足的条件数量。

首先,我们需要创建一个名为books
的索引,并定义它的映射(mappings)。映射用于指定每个字段的数据类型。在这个例子中,类别
和书名
字段都被定义为keyword
类型,这是因为我们需要进行精确匹配查询。
<br /> PUT /books<br /> {<br /> "mappings": {<br /> "properties": {<br /> "类别": { "type": "keyword" },<br /> "书名": { "type": "keyword" }<br /> }<br /> }<br /> }<br />
接下来,我们使用批量操作(bulk API)将一些示例数据导入到books
索引中。这些数据包括不同类别的书籍。
<br /> POST /books/_bulk<br /> { "index": { "_id": 1 } }<br /> { "类别": "文学", "书名": "我的阿勒泰" }<br /> { "index": { "_id": 2 } }<br /> { "类别": "文学", "书名": "平凡的世界" }<br /> { "index": { "_id": 3 } }<br /> { "类别": "科学", "书名": "时间简史" }<br /> { "index": { "_id": 4 } }<br /> { "类别": "文学", "书名": "百年孤独" }<br /> { "index": { "_id": 5 } }<br /> { "类别": "文学", "书名": "红楼梦" }<br />
现在,我们使用布尔查询来搜索类别
为“文学”并且书名
为“我的阿勒泰”的文档。这里使用的是must
子句,表示查询结果必须满足所有条件。
<br /> POST /books/_search<br /> {<br /> "query": {<br /> "bool": {<br /> "must": [<br /> { "term": { "类别": "文学" } },<br /> { "term": { "书名": "我的阿勒泰" } }<br /> ]<br /> }<br /> }<br /> }<br />
我们还可以使用filter
子句来执行相同的查询。filter
子句用于过滤文档,且不会影响文档的相关性评分。这在不需要计算相关性评分时可以提高查询性能。
<br /> POST /books/_search<br /> {<br /> "query": {<br /> "bool": {<br /> "filter": [<br /> { "term": { "类别": "文学" } },<br /> { "term": { "书名": "我的阿勒泰" } }<br /> ]<br /> }<br /> }<br /> }<br />
当我们执行上述查询时,期望返回的结果是books
索引中类别为“文学”且书名为“我的阿勒泰”的文档。无论是使用must
还是filter
子句,结果应该都是:
json<br /> {<br /> "hits": {<br /> "total": {<br /> "value": 1,<br /> "relation": "eq"<br /> },<br /> "hits": [<br /> {<br /> "_index": "books",<br /> "_id": "1",<br /> "_source": {<br /> "类别": "文学",<br /> "书名": "我的阿勒泰"<br /> }<br /> }<br /> ]<br /> }<br /> }<br />


<br /> POST /_search<br /> {<br /> "query": {<br /> "bool": {<br /> "must": [<br /> { "term": { "user.id": "kimchy" } }<br /> ],<br /> "filter": [<br /> { "term": { "tags": "production" } }<br /> ],<br /> "must_not": [<br /> {<br /> "range": {<br /> "age": { "gte": 10, "lte": 20 }<br /> }<br /> }<br /> ],<br /> "should": [<br /> { "term": { "tags": "env1" } },<br /> { "term": { "tags": "deployed" } }<br /> ],<br /> "minimum_should_match": 1,<br /> "boost": 1.0<br /> }<br /> }<br /> }<br />
must
子句:必须匹配的条件,文档必须包含user.id
为kimchy
。filter
子句:过滤条件,文档必须包含tags
为production
,但不会影响评分。must_not
子句:不匹配的条件,文档的age
字段不能在 10 到 20 之间。should
子句:可选匹配条件,至少需要匹配一个should
子句中的条件。这里要求tags
字段匹配env1
或deployed
。minimum_should_match
:至少需要匹配一个 should 子句中的条件。boost
:提升查询的整体评分。
为了展示这个 DSL ,我们需要创建一个索引并导入一些数据。假设我们要在 Easysearch 中创建一个索引users
,并插入一些测试数据。
创建索引
<br /> PUT /users<br /> {<br /> "mappings": {<br /> "properties": {<br /> "user.id": { "type": "keyword" },<br /> "tags": { "type": "keyword" },<br /> "age": { "type": "integer" }<br /> }<br /> }<br /> }<br />
批量导入数据
<br /> POST /users/_bulk<br /> { "index": { "_id": 1 } }<br /> { "user.id": "kimchy", "tags": ["production", "env1"], "age": 25 }<br /> { "index": { "_id": 2 } }<br /> { "user.id": "kimchy", "tags": ["production"], "age": 15 }<br /> { "index": { "_id": 3 } }<br /> { "user.id": "kimchy", "tags": ["deployed"], "age": 30 }<br /> { "index": { "_id": 4 } }<br /> { "user.id": "kimchy", "tags": ["test"], "age": 35 }<br /> { "index": { "_id": 5 } }<br /> { "user.id": "other", "tags": ["production"], "age": 25 }<br />
接下来执行布尔查询:
<br /> POST /users/_search<br /> {<br /> "query": {<br /> "bool": {<br /> "must": [<br /> { "term": { "user.id": "kimchy" } }<br /> ],<br /> "filter": [<br /> { "term": { "tags": "production" } }<br /> ],<br /> "must_not": [<br /> {<br /> "range": {<br /> "age": { "gte": 10, "lte": 20 }<br /> }<br /> }<br /> ],<br /> "should": [<br /> { "term": { "tags": "env1" } },<br /> { "term": { "tags": "deployed" } }<br /> ],<br /> "minimum_should_match": 1,<br /> "boost": 1.0<br /> }<br /> }<br /> }<br />
根据以上查询,预期返回的结果应该符合以下条件:
user.id
必须是kimchy
(由must
子句决定)。tags
必须包含production
(由filter
子句决定)。age
字段不在 10 到 20 之间(由must_not
子句决定)。tags
字段中至少包含env1
或deployed
中的一个(由should
子句和minimum_should_match
参数决定)。
json<br /> {<br /> "took": 1,<br /> "timed_out": false,<br /> "_shards": {<br /> "total": 1,<br /> "successful": 1,<br /> "skipped": 0,<br /> "failed": 0<br /> },<br /> "hits": {<br /> "total": {<br /> "value": 1,<br /> "relation": "eq"<br /> },<br /> "max_score": 1.3769134,<br /> "hits": [<br /> {<br /> "_index": "users",<br /> "_type": "_doc",<br /> "_id": "1",<br /> "_score": 1.3769134,<br /> "_source": {<br /> "user.id": "kimchy",<br /> "tags": ["production", "env1"],<br /> "age": 25<br /> }<br /> }<br /> ]<br /> }<br /> }<br />
SQL 搜索
Easysearch 直接支持 SQL 查询,无需额外安装插件,同时兼容 Elasticsearch 的 SQL 调用方式,还可以直接编写原生 SQL 查询。

以下是一些测试 SQL 语句的示例:
sql<br /> SELECT * FROM my_index;<br /> <br /> SELECT * FROM my_index LIMIT 2;<br /> <br /> SELECT * FROM my_index ORDER BY name;<br /> <br /> SELECT name AS full_name, age FROM my_index WHERE age > 25;<br /> <br /> SELECT name AS full_name, age FROM my_index WHERE age = 25;<br /> <br /> SELECT * FROM my_index WHERE age IS NULL;<br /> <br /> SELECT DISTINCT age FROM my_index;<br /> <br /> SELECT MIN(age), MAX(age), AVG(age) FROM my_index;<br /> <br /> SELECT age, COUNT(*) AS CNT FROM my_index GROUP BY age;<br />

使用 Easysearch 执行 SQL 查询
Easysearch 提供了对直接使用 SQL 查询的支持。以下是如何在 Easysearch 中通过 POST 请求使用_sql
端点进行查询的示例:
执行 SQL 查询非常简单,只需通过 POST 请求发送 SQL 查询即可。以下是一个示例:
<br /> POST /_sql<br /> {<br /> "query": "SELECT name AS full_name, age FROM my_index WHERE age > 25"<br /> }<br />
你也可以规定返回 JSON 格式:
<br /> POST /_sql?format=json<br /> {<br /> "query": "SELECT name AS full_name, age FROM my_index WHERE age > 25"<br /> }<br />
和 Elasticsearch 一样,Easysearch 允许你通过 POST 请求直接在集群上运行 SQL 查询,并返回查询结果。以下是一些常见的 SQL 查询示例及其对应的 POST 请求:
1.查询所有文档:
<br /> POST /_sql<br /> {<br /> "query": "SELECT * FROM my_index"<br /> }<br />
2.限制返回文档数:
<br /> POST /_sql<br /> {<br /> "query": "SELECT * FROM my_index LIMIT 2"<br /> }<br />
3.按字段排序:
<br /> POST /_sql<br /> {<br /> "query": "SELECT * FROM my_index ORDER BY name"<br /> }<br />
4.筛选条件查询:
<br /> POST /_sql<br /> {<br /> "query": "SELECT name AS full_name, age FROM my_index WHERE age > 25"<br /> }<br />
5.精确值查询:
<br /> POST /_sql<br /> {<br /> "query": "SELECT name AS full_name, age FROM my_index WHERE age = 25"<br /> }<br />
6.查询空值:
<br /> POST /_sql<br /> {<br /> "query": "SELECT * FROM my_index WHERE age IS NULL"<br /> }<br />
7.查询唯一值:
<br /> POST /_sql<br /> {<br /> "query": "SELECT DISTINCT age FROM my_index"<br /> }<br />
8.聚合函数查询:
<br /> POST /_sql<br /> {<br /> "query": "SELECT MIN(age), MAX(age), AVG(age) FROM my_index"<br /> }<br />
9.分组统计:
<br /> POST /_sql<br /> {<br /> "query": "SELECT age, COUNT(*) AS CNT FROM my_index GROUP BY age"<br /> }<br />

多表操作的 SQL 语句
以下是多表操作的 SQL 语句及其解释:
1.子查询:
sql<br /> SELECT * FROM `table1` t1 WHERE t1.id IN (SELECT id FROM `table2`)<br />
这个查询从table1
中选择所有字段的记录,其中这些记录的id
在table2
表中也存在。
2.内连接:
sql<br /> SELECT * FROM `table1` t1 JOIN `table2` t2 ON t1.id = t2.id<br />
这个查询进行内连接,从table1
和table2
中选择所有字段的记录,前提是table1
和table2
中id
相等。
3.左连接:
sql<br /> SELECT * FROM `table1` t1 LEFT JOIN `table2` t2 ON t1.id = t2.id<br />
这个查询进行左连接,从table1
和table2
中选择所有字段的记录,即使table2
中没有匹配的记录,也会返回table1
中的所有记录,未匹配到的部分会用 NULL 填充。
4.右连接:
sql<br /> SELECT * FROM `table1` t1 RIGHT JOIN `table2` t2 ON t1.id = t2.id<br />
这个查询进行右连接,从table1
和table2
中选择所有字段的记录,即使table1
中没有匹配的记录,也会返回table2
中的所有记录,未匹配到的部分会用 NULL 填充。
假设我们有两个索引table1
和table2
,对应于 SQL 中的两个表。
创建索引table1
:
<br /> PUT /`table1`<br /> {<br /> "mappings": {<br /> "properties": {<br /> "id": { "type": "integer" },<br /> "name": { "type": "text" }<br /> }<br /> }<br /> }<br />
创建索引table2
:
<br /> PUT /`table2`<br /> {<br /> "mappings": {<br /> "properties": {<br /> "id": { "type": "integer" },<br /> "value": { "type": "text" }<br /> }<br /> }<br /> }<br />
导入数据到table1
:
<br /> POST /`table1`/_bulk<br /> { "index": { "_id": 1 } }<br /> { "id": 1, "name": "Alice" }<br /> { "index": { "_id": 2 } }<br /> { "id": 2, "name": "Bob" }<br /> { "index": { "_id": 3 } }<br /> { "id": 3, "name": "Charlie" }<br /> { "index": { "_id": 4 } }<br /> { "id": 4, "name": "David" }<br />
导入数据到table2
:
<br /> POST /`table2`/_bulk<br /> { "index": { "_id": 1 } }<br /> { "id": 1, "value": "Value1" }<br /> { "index": { "_id": 2 } }<br /> { "id": 2, "value": "Value2" }<br /> { "index": { "_id": 5 } }<br /> { "id": 5, "value": "Value5" }<br /> { "index": { "_id": 6 } }<br /> { "id": 6, "value": "Value6" }<br />
导入数据后,可以使用 SQL 来执行这些查询:
1.子查询:
<br /> POST /_sql<br /> {<br /> "query": "SELECT * FROM `table1` WHERE id IN (SELECT id FROM `table2`)"<br /> }<br />
2.内连接:
<br /> POST /_sql<br /> {<br /> "query": "SELECT * FROM `table1` t1 JOIN `table2` t2 ON t1.id = t2.id"<br /> }<br />
3.左连接:
<br /> POST /_sql<br /> {<br /> "query": "SELECT * FROM `table1` t1 LEFT JOIN `table2` t2 ON t1.id = t2.id"<br /> }<br />
4.右连接:
<br /> POST /_sql<br /> {<br /> "query": "SELECT * FROM `table1` t1 RIGHT JOIN `table2` t2 ON t1.id = t2.id"<br /> }<br />
效果如下:

SQL 全文检索
match
和match_phrase
是 Easysearch 中用于全文搜索的查询类型,它们在处理文本匹配方面有不同的用途:
1.match
查询:
match
查询用于对文档进行全文搜索。- 它将搜索关键词进行分词,并对这些分词后的词项进行搜索。
- 适用于查询单个或多个字段,可以进行布尔操作(如 “AND”, “OR”)。
- 例如,搜索 “Easysearch is powerful” 会被分词为 "Easysearch ", “is”, “powerful” 三个词,然后对这三个词进行搜索,文档中包含这些词的都会被认为是匹配的。
json<br /> {<br /> "query": {<br /> "match": {<br /> "content": "Easysearch is powerful"<br /> }<br /> }<br /> }<br />
2.match_phrase
查询:
match_phrase
查询用于短语搜索。- 它要求搜索的短语必须在文档中出现且词的顺序相同,词之间的间隔也必须与查询中的短语相同。
- 适用于需要精确匹配短语的场景。
- 例如,搜索 “Easysearch is powerful” 时,只有包含这个确切短语的文档才会被认为是匹配的。
json<br /> {<br /> "query": {<br /> "match_phrase": {<br /> "content": "Easysearch is powerful"<br /> }<br /> }<br /> }<br />
总结来说,match
更灵活,用于一般的关键词搜索,而match_phrase
则用于需要精确匹配短语的搜索。
SQL 全文检索示例
我们先造一些数据,然后使用 SQL 来进行全文检索。
批量导入数据:
<br /> POST /table3/_bulk<br /> { "index": { "_id": 1 } }<br /> { "id": 1, "test": "The quick brown fox jumps over the lazy dog" }<br /> { "index": { "_id": 2 } }<br /> { "id": 2, "test": "Foxes are wild animals" }<br /> { "index": { "_id": 3 } }<br /> { "id": 3, "test": "Jump high to catch the ball" }<br /> { "index": { "_id": 4 } }<br /> { "id": 4, "test": "Some animals can jump very high" }<br /> { "index": { "_id": 5 } }<br /> { "id": 5, "test": "The lazy dog sleeps all day" }<br /> { "index": { "_id": 6 } }<br /> { "id": 6, "test": "The foxes jump all day" }<br />
执行全文检索的 SQL 查询:
sql<br /> SELECT * FROM table3;<br /> <br /> SELECT * FROM table3 WHERE match(test, 'jump');<br /> <br /> SELECT * FROM table3 WHERE match_phrase(test, 'foxes jump');<br />

总结
随着数据量的不断增加,高效的数据搜索和分析变得尤为重要。Elasticsearch 以其强大的全文搜索能力和灵活的数据处理能力成为行业标准。Easysearch 作为 Elasticsearch 的优化版本,不仅继承了其强大的功能,还在性能和安全性上做了进一步的提升,为企业提供了一个高效、稳定且易于迁移的搜索引擎解决方案。通过深入了解这些技术和实践其应用,开发者和企业能够更好地利用这些工具来应对现代数据挑战,推动业务的持续发展和创新。
关于 Easysearch 有奖征文活动

无论你是 Easysearch 的老用户,还是第一次听说这个名字,只要你对 INFINI Labs 旗下的 Easysearch 产品感兴趣,或者是希望了解 Easysearch,都可以参加这次活动。
详情查看:[Easysearch 征文活动](https://infinilabs.cn/blog/202 ... ukong/)
作者:韩旭,亚马逊云技术支持,亚马逊云科技技领云博主,目前专注于云计算开发和大数据领域。
原文:https://infinilabs.cn/blog/202 ... ntax/