2012-09-07 3 views
1

User 개체를 RavenDB에 저장합니다. 각 User에는 User.Id 속성이 있습니다.RavenDB를 사용하여 '외래 키'와 관련된 항목 목록을 효율적으로 검색하는 방법

는 또한 두 User.Id을 연결하는 Relationship 클래스는 다음과 같이 멘토/멘티 관계를 만들어 함께에요 있습니다

public class User 
{ 
    public string Id { get; set; } 
    public string UserName { get; set; } 
    ... more properties 
} 

public class Relationship 
{ 
    public string Id { get; set; } 
    public string MentorId { get; set; } 
    public string MenteeId { get; set; } 
    public RelationshipStatus Status { get; set; } 
} 

가 지금은 주어진 멘토에 대한 멘티의 목록을 검색 할 수 있습니다. 나는 다음과 같은 방법으로이 작업을 수행 한 : 이것은 단지 잘 작동하는 것 같다하지만 내 어깨에 코딩 - 천사가 그녀에게 IDocumentSession (dB)의 중첩 사용에서 나오는 냄새에 코와를 주름입니다

public static List<User> GetMentees(IDocumentSession db, string mentorId) 
{ 
    var mentees = new List<User>(); 
    db.Query<Relationship>() 
      .Where(r => r.MentorId == mentorId) 
      .Select(r => r.MenteeId) 
      .ForEach(id => mentees.Add(db.Load<User>(id))); 
    return mentees; 
} 

복수 Load 전화가 필요하며 Mentees 목록을 작성하십시오.

모범 사례 RavenDB 구문을 사용하여이 방법을 최적화하려면 어떻게해야합니까? 나를 위해 데이터베이스에 여러 통화의 문제를 해결 @Jonah 희망 고 (아래 허용 대답 참조)

편집 감사합니다. 또한 'Memoize'라는 새로운 확장 메서드를 만들어 외부 'mentees'결과 목록 (위의 코드 참조)에 대한 필요성을 제거했습니다.

여기에 최적화 된 코드가 있습니다. 언제든지 의견을 말하고 수정하십시오.

Linq의

public static List<User> GetMentees(IDocumentSession db, string mentorId) 
{ 
    return db.Query<Relationship>() 
      .Customize(x => x.Include<Relationship>(o => o.MenteeId)) 
      .Where(r => r.MentorId == mentorId) 
      .Memoize() 
      .Select(r => db.Load<User>(r.MenteeId)) 
      .ToList(); 
} 

확장 방법

public static List<T> Memoize<T>(this IQueryable<T> target) 
{ 
    return target.ToList(); 
} 

:이 확장 방법 (정말입니다) 완전히 불필요한 것처럼 보일 수 있지만, 내 괴짜 글 랜드를 자극 ToList()이라는 함수를 호출해야하는데 목록을 만들지 않고 강제로 L을 실행해야합니다. inq 문. 따라서 내 확장 메서드는 ToList()의 이름을 훨씬 더 정확하게 Memoize()으로 바꿉니다.

답변

1

당신은 각 관계의 오프 관련 사용자 개체 포함 레이븐에게하는 .Include query customization를 사용하는 것이 좋습니다 :

db.Query<Relationship>() 
      .Customize(x => x.Include<Relationship>(o => o.MenteeId)) 
      .Where(r => r.MentorId == mentorId) 
      .Select(r => r.MenteeId) 
      .ForEach(id => mentees.Add(db.Load<User>(id))); // .Load no longer makes a call to the DB; it's already loaded into the session! 

Relevant documentation here :

통화가 (로드하기)를 완전히 해결 클라이언트 측 (즉, RavenDB 서버에 대한 추가 요청이 없음). [관련] 객체가 .Include 호출을 통해 이미 검색 되었기 때문에.

관련 문제