Nestjs项目实战 使用Elasticsearch进行全文搜索
在Nestjs项目中集成Elasticsearch进行全文搜索时,如何正确配置Elasticsearch模块?
我按照官方文档进行了基本配置,但始终无法建立连接,出现了"No Living connections"的错误提示。具体应该如何排查和解决这个问题?
另外,在Nestjs中创建Elasticsearch索引的最佳实践是什么?是否需要单独编写脚本,还是可以直接在应用启动时自动创建?
对于中文全文搜索,应该如何设置分词器和映射字段才能获得较好的搜索结果?能否分享一些实际项目中的配置示例?
最后,在性能方面,有哪些优化Elasticsearch查询效率的技巧?比如批量操作、缓存策略等方面的实践经验。
在NestJS项目中使用Elasticsearch进行全文搜索,首先需要安装@nestjs/elasticsearch
和elasticsearch
库。先配置Elasticsearch模块:
npm install @nestjs/elasticsearch elasticsearch
创建一个Elasticsearch服务:
import { Injectable } from '@nestjs/common';
import { Client, ElasticsearchService } from '@nestjs/elasticsearch';
@Injectable()
export class SearchService {
constructor(private readonly elasticsearchService: ElasticsearchService) {}
async indexDocument(index: string, id: string, body: any) {
return this.elasticsearchService.index({ index, id, body });
}
async search(index: string, query: any) {
return this.elasticsearchService.search({ index, body: query });
}
}
接着,在控制器中使用该服务实现搜索功能:
import { Controller, Get, Param } from '@nestjs/common';
import { SearchService } from './search.service';
@Controller('search')
export class SearchController {
constructor(private readonly searchService: SearchService) {}
@Get(':index/_search')
async search(@Param('index') index: string, @Body() query: any) {
const result = await this.searchService.search(index, query);
return result.body;
}
}
最后,通过NestJS的依赖注入机制管理Elasticsearch客户端,完成全文搜索功能。记得在app.module.ts
中注册ElasticsearchModule,并配置ElasticsearchClient选项。
在Nestjs项目中使用Elasticsearch进行全文搜索的步骤如下:
-
安装依赖
首先需要安装[@nestjs](/user/nestjs)/elasticsearch
和elasticsearch
包:npm install [@nestjs](/user/nestjs)/elasticsearch elasticsearch
-
配置Elasticsearch模块
创建一个Elasticsearch服务,在app.module.ts
中注册它:import { Module } from '[@nestjs](/user/nestjs)/common'; import { ElasticsearchModule } from '[@nestjs](/user/nestjs)/elasticsearch'; [@Module](/user/Module)({ imports: [ ElasticsearchModule.register({ node: 'http://localhost:9200', // Elasticsearch地址 }), ], }) export class AppModule {}
-
创建数据模型
假设我们有一个文章模型,包含标题和内容字段。首先在Elasticsearch中创建索引:import { Injectable } from '[@nestjs](/user/nestjs)/common'; import { ElasticsearchService } from '[@nestjs](/user/nestjs)/elasticsearch'; [@Injectable](/user/Injectable)() export class ArticleService { constructor(private readonly elastic: ElasticsearchService) {} async createIndex(indexName: string) { await this.elastic.indices.create({ index: indexName, body: { mappings: { properties: { title: { type: 'text' }, content: { type: 'text' }, }, }, }, }); } }
-
实现全文搜索
编写搜索方法,利用Elasticsearch的query_string
查询:async search(indexName: string, query: string) { const result = await this.elastic.search({ index: indexName, body: { query: { query_string: { query, }, }, }, }); return result.hits.hits; }
-
使用服务
在控制器中调用服务进行搜索:[@Controller](/user/Controller)('articles') export class ArticleController { constructor(private readonly articleService: ArticleService) {} @Get('search') async search(@Query('q') query: string) { return this.articleService.search('article_index', query); } }
这样就完成了一个简单的基于Nestjs和Elasticsearch的全文搜索功能。
NestJS项目实战:使用Elasticsearch进行全文搜索
基本配置
首先安装必要的依赖:
npm install @nestjs/elasticsearch @elastic/elasticsearch
然后在NestJS模块中配置Elasticsearch:
// elasticsearch.module.ts
import { Module } from '@nestjs/common';
import { ElasticsearchModule } from '@nestjs/elasticsearch';
@Module({
imports: [
ElasticsearchModule.register({
node: 'http://localhost:9200',
}),
],
exports: [ElasticsearchModule],
})
export class ElasticsearchCustomModule {}
服务层实现
创建一个搜索服务:
// search.service.ts
import { Injectable } from '@nestjs/common';
import { ElasticsearchService } from '@nestjs/elasticsearch';
@Injectable()
export class SearchService {
constructor(private readonly elasticsearchService: ElasticsearchService) {}
async createIndex(index: string) {
return this.elasticsearchService.indices.create({ index });
}
async indexDocument(index: string, id: string, document: any) {
return this.elasticsearchService.index({
index,
id,
body: document,
});
}
async search(index: string, query: string) {
return this.elasticsearchService.search({
index,
body: {
query: {
multi_match: {
query,
fields: ['title', 'content'],
},
},
},
});
}
async deleteDocument(index: string, id: string) {
return this.elasticsearchService.delete({
index,
id,
});
}
}
控制器实现
// search.controller.ts
import { Controller, Get, Post, Body, Query } from '@nestjs/common';
import { SearchService } from './search.service';
@Controller('search')
export class SearchController {
constructor(private readonly searchService: SearchService) {}
@Post('index')
async indexDocument(
@Body('index') index: string,
@Body('id') id: string,
@Body('document') document: any,
) {
return this.searchService.indexDocument(index, id, document);
}
@Get()
async search(@Query('q') query: string, @Query('index') index: string) {
return this.searchService.search(index, query);
}
}
高级功能
- 批量索引:
async bulkIndex(index: string, documents: Array<{id: string; document: any}>) {
const body = documents.flatMap(doc => [
{ index: { _index: index, _id: doc.id } },
doc.document,
]);
return this.elasticsearchService.bulk({ body });
}
- 聚合查询:
async aggregateByField(index: string, field: string) {
return this.elasticsearchService.search({
index,
body: {
aggs: {
group_by_field: {
terms: { field }
}
}
}
});
}
- 分页查询:
async searchWithPagination(index: string, query: string, page: number, size: number) {
return this.elasticsearchService.search({
index,
from: (page - 1) * size,
size,
body: {
query: {
multi_match: {
query,
fields: ['title', 'content'],
},
},
},
});
}
最佳实践
- 为不同的数据类型创建不同的索引
- 使用映射(mapping)定义字段类型
- 考虑使用别名(alias)来管理索引
- 实现重试机制处理连接问题
- 监控Elasticsearch集群健康状态
希望这个实战指南能帮助你在NestJS项目中集成Elasticsearch实现全文搜索功能!