Page History
...
- 비교적 심플한 코드작성으로 CRUD 테스트 수행이 완료되었습니다.
CQRS로의 여정
CRUD만 이용하려고 RavenDB를 선택한것은 아니고~ Akka.net의 Persist기능과 연동되어
단일 DB에서 다양한 검색수행
반경검색/FullText검색및 Vector검색을 단일DB에서 효율적으로 검색해낼수 있습니다.
| Code Block | ||
|---|---|---|
| ||
public class TravelReviewRepository
{
private readonly IDocumentStore _store;
public TravelReviewRepository(IDocumentStore store)
{
_store = store ?? throw new ArgumentNullException(nameof(store));
}
public void AddReview(TravelReview review)
{
using (var session = _store.OpenSession())
{
session.Store(review);
session.SaveChanges();
}
}
public List<TravelReview> SearchReviews(string keyword, double latitude, double longitude, double radiusKm, string category = null)
{
using (var session = _store.OpenSession())
{
// 명시적으로 변수로 선언
var keywordValue = keyword;
var categoryValue = category;
IRavenQueryable<TravelReview> query = session.Query<TravelReview>();
if (!string.IsNullOrEmpty(keywordValue))
{
query = query.Search(r => r.Content, keywordValue); // FullText검색
}
if (!string.IsNullOrEmpty(categoryValue))
{
query = query.Where(r => r.Category == categoryValue); // 일반적인 필터
}
// RavenDB에서 서버 측 필터링 후 클라이언트 측에서 반경 필터링
var results = query.ToList();
return results.Where(r =>
6371 * Math.Acos(
Math.Cos(DegToRad(latitude)) * Math.Cos(DegToRad(r.Latitude)) *
Math.Cos(DegToRad(r.Longitude) - DegToRad(longitude)) +
Math.Sin(DegToRad(latitude)) * Math.Sin(DegToRad(r.Latitude))
) <= radiusKm).ToList();
}
}
public List<TravelReview> SearchReviewsByRadius(double latitude, double longitude, double radiusKm)
{
using (var session = _store.OpenSession())
{
return session.Query<TravelReview>()
.Spatial(
r => r.Point(x => x.Latitude, x => x.Longitude),
criteria => criteria.WithinRadius(radiusKm, latitude, longitude))
.ToList();
}
}
public List<TravelReview> SearchReviewsByVector(float[] queryVector, int topN = 5)
{
using (var session = _store.OpenSession())
{
var results = session.Advanced
.RawQuery<TravelReview>(
@"from index 'TravelReview_Index'
where TitleVector vector $queryVector
order by score() desc
limit $topN")
.AddParameter("queryVector", queryVector)
.AddParameter("topN", 10)
.ToList();
return results;
}
}
private double DegToRad(double degrees)
{
return degrees * (Math.PI / 180);
}
} |
- Vector검색과 같이 특수한 검색기능은 RawQuery를 사용해야하며 나머지는 Linq를 이용할수 있습니다.
- Raven전용 네이티브 쿼리가 익숙하지않아 아직 성공은 못함 ( raven 6.x부터 지원 )
CQRS로의 여정
CRUD또는 검색기능만 이용하려고 RavenDB를 조사한것은 아니며 Akka.net의 Persist기능이 제공하는 CQRS장치와 연동이됨으로
이벤트 소싱이 필요한 기능을 만들고자 할때, 가장 심플한 방식으로 구현하고 강력하게 이용할수 있는 방식중 하나가 될수 있습니다이벤트 소싱을 액터모델의 Persitent 기능과 함께 심플하게 이용할수 있기때문입니다.
...

