Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

단일 DB에서 다양한 검색수행

반경검색/FullText검색및 Vector검색을 단일DB에서 효율적으로 검색해낼수 Vector검색등 고급 검색기능을 단일DB만사용해  검색할수 있습니다.

Code Block
themeEmacs
using ActorLib.Persistent.Model;
using Raven.Client.Documents;
using Raven.Client.Documents.Indexes.Vector;
using Raven.Client.Documents.Linq;

namespace ActorLib.Persistent;

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[] queryVectorvector, int topN = 5)
    {
        using (var session = _store.OpenSession())
        {
            var results = session.AdvancedQuery<TravelReview>()
                .RawQuery<TravelReview>VectorSearch(
                    @"from index 'TravelReview_Index'field => field.WithEmbedding(x => x.TagsEmbeddedAsSingle, VectorEmbeddingType.Single),
                    queryVector  where TitleVector vector $queryVector=> queryVector.ByEmbedding(new RavenVector<float>(vector)),
                      order by score() desc0.85f,
                      limit $topN"topN)
                .AddParameter("queryVector", queryVectorCustomize(x => x.WaitForNonStaleResults())
                .AddParameter("topN", 10)
ToList();

                .ToList();

            return results;
        }
    }

    private double DegToRad(double degrees)
    {
        return degrees * (Math.PI / 180);
    }
}

Image Removed

Image Added

CQRS로의 여정

CRUD또는 검색기능만 이용하려고 RavenDB를 조사한것은 아니며 Akka.net의 Persist기능이 제공하는 CQRS장치와 연동이됨으로

...