Elasticsearch, Kibana 및 NestJS를 사용하여 전체 자동 완성 검색 애플리케이션을 만드는 방법 - 3부
이 기사에서는 Elasticsearch에 연결하고 쿼리할 NodeJS 코드를 작성합니다.
Elasticsearch에 데이터 로드
코드를 효과적으로 작성하려면
elasticsearch
에 데이터를 로드해야 합니다. Kaggle( Download it here )의 샘플 데이터 세트를 사용할 것입니다.아래 4단계를 따라 Elasticsearch에 로드합니다.
Get started by adding integrations
에서 파일 업로드를 클릭합니다.여기까지 했다면 데이터를 elasticsearch로 성공적으로 가져온 것입니다.
샘플 문의
DevTools로 이동(화면 왼쪽 상단의 햄버거 > Management > DevTools까지 아래로 스크롤)
아래 쿼리 실행(선택 후 재생 버튼 클릭)
GET tmdb_movies/_search
이것을 보면 우리는 갈 수 있습니다!
자, 코딩에 빠져볼까요 😊?
NestJ
NestJS is a progressive Node. js framework that helps build server-side applications. Nest extends Node. js frameworks like Express or Fastify adding modular organization and a wide range of other libraries to take care of repetitive tasks. It's open-source, uses TypeScript, and is a very versatile Node.
NestJs 애플리케이션 만들기
아래 명령을 실행하여 nestcli를 설치하고 새 NestJs 애플리케이션을 생성합니다(기사에서 앱 이름은 nest-elastic임).
$ npm i -g @nestjs/cli
$ nest new nest-elastic
패키지 관리자를 선택하라는 메시지가 표시되며 npm, yarn 또는 pnpm을 선택할 수 있습니다. 원사를 선택하겠습니다(원하는 다른 원사 선택 가능 😉). 프로젝트가 설정되고 코딩할 준비가 되었습니다!
앱에 Elasticsearch 추가
아래 명령을 실행하여 Elasticsearch를
nest-elastic
및 기타 종속성에 추가합니다.yarn add @elastic/elasticsearch @nestjs/elasticsearch @nestjs/config
루트 폴더에 다음 내용이 포함된
.env
파일을 추가합니다.ELASTICSEARCH_NODE=https://localhost:9200
ELASTICSEARCH_USERNAME=elastic
ELASTICSEARCH_PASSWORD=elasticPasswordGoesHere
ELASTICSEARCH_MAX_RETRIES=10
ELASTICSEARCH_REQ_TIMEOUT=50000
ELASTICSEARCH_INDEX=tmdb_movies
Elasticsearch를 사용하여 검색만 처리하는 별도의 모듈을 만들어 보겠습니다. 간단한 단축키는 아래 명령을 사용하는 것입니다(원하는 경우 수동으로 수행할 수도 있음).
nest g resource search
아래 내용이 포함되도록
search.module.ts
를 업데이트합니다.import { Module } from '@nestjs/common';
import { SearchService } from './search.service';
import { SearchController } from './search.controller';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { ElasticsearchModule } from '@nestjs/elasticsearch';
@Module({
imports: [
ConfigModule,
ElasticsearchModule.registerAsync({
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => ({
node: configService.get('ELASTICSEARCH_NODE'),
auth: {
username: configService.get('ELASTICSEARCH_USERNAME'),
password: configService.get('ELASTICSEARCH_PASSWORD'),
},
maxRetries: configService.get('ELASTICSEARCH_MAX_RETRIES'),
requestTimeout: configService.get('ELASTICSEARCH_REQ_TIMEOUT'),
}),
inject: [ConfigService],
}),
],
controllers: [SearchController],
providers: [SearchService],
exports: [SearchService],
})
export class SearchModule {}
아래 내용으로 업데이트
search.service.ts
:import { ConfigService } from '@nestjs/config';
import { Injectable } from '@nestjs/common';
import { ElasticsearchService } from '@nestjs/elasticsearch';
type dataResponse = {
UnitPrice: number;
Description: string;
Quantity: number;
Country: string;
InvoiceNo: string;
InvoiceDate: Date;
CustomerID: number;
StockCode: string;
};
@Injectable()
export class SearchService {
constructor(
private readonly esService: ElasticsearchService,
private readonly configService: ConfigService,
) {}
async search(search: {key: string}) {
let results = new Set();
const response = await this.esService.search({
index: this.configService.get('ELASTICSEARCH_INDEX'),
body: {
size: 50,
query: {
match_phrase: search
},
},
});
const hits = response.hits.hits;
hits.map((item) => {
results.add(item._source as dataResponse);
});
return { results: Array.from(results), total: response.hits.total };
}
}
이제 영화 모듈을 추가해 보겠습니다.
nest g resource movies
아래 내용으로 업데이트
movies.controller.ts
:import { SearchService } from './../search/search.service';
import { Body, Controller, Post } from '@nestjs/common';
@Controller('movies')
export class MoviesController {
constructor(private readonly searchService: SearchService) {}
@Post('search')
async search(@Body() body) {
return await this.searchService.search(body.data);
}
}
그럼
movies.module.ts
import { SearchModule } from './../search/search.module';
import { Module } from '@nestjs/common';
import { MoviesService } from './movies.service';
import { MoviesController } from './movies.controller';
@Module({
imports: [SearchModule],
controllers: [MoviesController],
providers: [MoviesService],
})
export class MoviesModule {}
마지막으로 업데이트
app.module.ts
import { MoviesModule } from './movies/movies.module';
import { ConfigModule } from '@nestjs/config';
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { SearchModule } from './search/search.module';
@Module({
imports: [MoviesModule, ConfigModule.forRoot(), SearchModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
package.json
는 다음과 같아야 합니다.{
"name": "nest-elastic",
"version": "0.0.1",
"description": "",
"author": "Yusuf Ganiyu",
"private": true,
"license": "UNLICENSED",
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
"start:prod": "node dist/main",
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
"test": "jest",
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json"
},
"dependencies": {
"@elastic/elasticsearch": "^8.4.0",
"@nestjs/common": "^9.0.0",
"@nestjs/config": "^2.2.0",
"@nestjs/core": "^9.0.0",
"@nestjs/elasticsearch": "^9.0.0",
"@nestjs/mapped-types": "*",
"@nestjs/platform-express": "^9.0.0",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0"
},
"devDependencies": {
"@nestjs/cli": "^9.0.0",
"@nestjs/schematics": "^9.0.0",
"@nestjs/testing": "^9.0.0",
"@types/express": "^4.17.13",
"@types/jest": "28.1.4",
"@types/node": "^16.0.0",
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^8.0.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "28.1.2",
"prettier": "^2.3.2",
"source-map-support": "^0.5.20",
"supertest": "^6.1.3",
"ts-jest": "28.0.5",
"ts-loader": "^9.2.3",
"ts-node": "^10.0.0",
"tsconfig-paths": "4.0.0",
"typescript": "^4.3.5"
},
"jest": {
"moduleFileExtensions": [
"js",
"json",
"ts"
],
"rootDir": "src",
"testRegex": ".*\\.spec\\.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
},
"collectCoverageFrom": [
"**/*.(t|j)s"
],
"coverageDirectory": "../coverage",
"testEnvironment": "node"
}
}
앱 실행
yarn start:dev
를 사용하여 개발 환경에서 앱을 실행할 수 있습니다.테스트
전체source code here에 액세스할 수 있습니다.
요약
이 기사에서는 kibana를 사용하여 Elastic으로 데이터를 가져오고 NestJs 백엔드 앱을 Elasticsearch의 기능을 활용하도록 연결할 수 있습니다.
다음 기사에서는 Elasticsearch의 결과를 실시간으로 쿼리하고 시각화하는 간단한 프런트엔드를 구축할 것입니다.
읽어 주셔서 감사합니다!
Reference
이 문제에 관하여(Elasticsearch, Kibana 및 NestJS를 사용하여 전체 자동 완성 검색 애플리케이션을 만드는 방법 - 3부), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/airscholar/how-to-create-a-full-autocomplete-search-application-with-elasticsearch-kibana-and-nestjs-part-3-14lp텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)