Page History
Tip |
---|
쿼리 DSL은 ORM에 있어서도, 검색엔진을 사용하는 검색 쿼리 사용에 있어서도 복잡한 검색기능을 단순하게 구현 하기위한 좋은 방법중에 하나이며 닷넷 어플리케이션내에서 DSL검색 방식을 사용하기에 적합한 NEST를 선택하였습니다. |
설정
주요 Nuget 의존성 라이브러리
Code Block |
---|
<PackageReference Include="NEST" Version="7.5.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.3" /> <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="2.2.0" /> |
...
사용자의 검색 요청은 엘라서틱 서치엔진 API를 직접 사용할 예정이기때문에 이 경우 ORM의 성능은 큰 이슈가 되지 못합니다.
인덱싱이 수정 되고 있을때(풀인덱싱,부분 대량업데이트,실시간성 부분업데이트) 검색(Read)의 성능을 영향받지 않고 -인덱스 데이터의 스왑
RDB보다 훨씬 다양하고 복합적인(풀텍스트,반경검색,검색과 동시에 집계처리등) 순간검색을 위해 인덱스를 효율적으로 설정하고 관리하는 전략이 필요합니다.
다음과 같이 대량 업데이트에 최적화된 Bulk 전략도 필요하게 됩니다.
App 설정
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
},
"AppSettings": {
"DBConnection": "server=localhost;port=13306;database=search;user=root;password=root;"
},
"elasticsearch": {
"index": "baseitem",
"url": "http://localhost:9200/"
}
}
|
엘라서틱 Config
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
using System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Nest;
using SearchApi.Entity;
namespace SearchApi.Config
{
public static class ElasticsearchExtensions
{
public static void AddElasticsearch(
this IServiceCollection services, IConfiguration configuration)
{
var url = configuration["elasticsearch:url"];
var defaultIndex = configuration["elasticsearch:index"];
var settings = new ConnectionSettings(new Uri(url))
.DefaultIndex(defaultIndex)
.DefaultMappingFor<SearchGoods>(m => m
.PropertyName(p => p.no, "id")
);
var client = new ElasticClient(settings);
services.AddSingleton<IElasticClient>(client);
}
}
} |
StartUp 설정
Code Block | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
public void ConfigureServices(IServiceCollection services)
{
services.AddElasticsearch(Configuration);
....... |
검색 기능 추가
검색 Entity정의
Code Block | ||||
---|---|---|---|---|
| ||||
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace SearchApi.Entity
{
[Table("tbl_search_goods")]
public class SearchGoods
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int no { get; set; }
[Column("goods_no")]
public string goodsNo { get; set; }
[Column("name_kr")]
public string nameKr { get; set; }
[Column("name_en")]
public string nameEn { get; set; }
public string category1 { get; set; }
public string category2 { get; set; }
public string category3 { get; set; }
public int price { get; set; }
[Column("view_cnt")]
public int viewCnt { get; set; }
[Column("sale_cnt")]
public int saleCnt { get; set; }
public string terms { get; set; }
public string tags { get; set; }
[Column("url_pc")]
public string urlPc { get; set; }
[Column("url_mobile")]
public string urlMobile { get; set; }
[Column("image_url1")]
public string imageUrl1 { get; set; }
[Column("image_url2")]
public string imageUrl2 { get; set; }
}
} |
검색데이터의 정의는 익숙한 RDB 모델(엔티티)로부터 먼저 시작하여
검색엔진의 문서의 검색 속성을 일치화할것입니다.
검색 Repository for RDB
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
using System; using Microsoft.EntityFrameworkCore; using SearchApi.Config; using SearchApi.Entity; namespace SearchApi.Repositories { public class SearchRepository : DbContext { private const string database = "search"; private readonly AppSettings appSettings; private readonly bool isEncript; public string DebugConString { get; set; } public DbSet<SearchGoods> searchGoods { get; set; } public SearchRepository(DbContextOptions<SearchRepository> options, AppSettings _appSettings) : base(options) { appSettings = _appSettings; if (!appSettings.DBConnection.Contains("localhost")) { isEncript = true; } } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!optionsBuilder.IsConfigured) { string dbOption = ""; string dbConnectionString = string.Empty; if (isEncript) { throw new NotImplementedException("암호화 모듈을 적용하시오~"); } else { dbConnectionString = appSettings.DBConnection + $"database={database};" + dbOption; } optionsBuilder.UseMySql(dbConnectionString); } } } } |
검색 데이터의 원본은 RDB 이며 ORM을 활용합니다.
닷넷코어에서 Entity설정은 다음을 추가참고합니다.
Link : https://docs.microsoft.com/en-us/ef/core/
DI를 통한 엘라서틱 서치 클라이언트 사용
Code Block | ||
---|---|---|
| ||
using Microsoft.AspNetCore.Mvc;
using Nest;
namespace SearchApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
private readonly IElasticClient _elasticClient;
public TestController(IElasticClient elasticClient)
{
_elasticClient = elasticClient;
}
}
} |
IElasticClient 객체가 실제 엘라서틱서버 연결설정이 완료되어
사용준비가 되면 기본 설정이 완료 되었으며
다음장에서는 최초 검색데이터를 인덱싱→인덱스 한 상태에서
기본적인 검색 기능을 구현하는것에대해 알아 보겠습니다.
참고링크:
- https://miroslavpopovic.com/posts/2018/07/elasticsearch-with-aspnet-core-and-docker
- https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/writing-analyzers.html
- https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/testing-analyzers.html