2013-02-12 10 views
5

Mam strukturę dokumentu tak:RavenDb Index statyczny: zapytanie o kolekcji obiektów podrzędnych

Employer => Positions => RequiredSkills

pracodawca kolekcję stanowiska
Pozycje mieć kolekcję RequiredSkill.
Wymagany skill składa się z umiejętności (ciąg) i umiejętności (enum).

Jeśli korzystam z indeksu dynamicznego, wydaje się, że zwraca on grzywnę firmy, jednak chcę użyć indeksu do wypełnienia modeli widoku MVC, aby powrócić do interfejsu użytkownika.

Jestem naprawdę nowy w Raven, więc przepraszam za zrobienie czegoś głupiego/niepotrzebnego!

Mam następujące odwzorowanie:

public class PositionSearch : AbstractIndexCreationTask<Employer> 
    { 
     public PositionSearch() 
     { 
      Map = employers => 
        from employer in employers 
        from position in employer.Positions 
        select new 
         { 
          EmployerId = employer.Id, 
          EmployerName = employer.Name, 
          PositionId = position.Id, 
          PositionTitle = position.Title, 
          position.Location, 
          position.Description, 
          RequiredSkills = position.RequiredSkills 
         }; 

      StoreAllFields(FieldStorage.Yes); 

      Index("RequiredSkills_Skill", FieldIndexing.Analyzed); 
     } 
    } 

Jednak gdy próbuję wykonać następujące zapytanie:

var results = session.Query<PositionSearchResultModel, PositionSearch>() 
    .Customize(x => x.WaitForNonStaleResults()) 
    .Where(x=>x.RequiredSkills.Any(y=>y.Skill == "SkillName")) 
    .ProjectFromIndexFieldsInto<PositionSearchResultModel>() 
    .ToList(); 

pojawia się następujący błąd:

System.ArgumentException: 
    The field 'RequiredSkills_Skill' is not indexed, 
    cannot query on fields that are not indexed 

Can Czy ktoś widzi, co robię źle, lub sugeruje mi inne podejście?

Dzięki,

James

UPDATE moim zdaniem model - Thanks:

public class PositionSearchResultModel 
{ 
    public PositionSearchResultModel() 
    { 
     RequiredSkills = new HashSet<SkillProficiency>(); 
    } 

    public string EmployerId { get; set; } 
    public string EmployerName { get; set; } 
    public string PositionId { get; set; } 
    public string PositionTitle { get; set; } 
    public string Location { get; set; } 
    public string Description { get; set; } 
    public ICollection<SkillProficiency> RequiredSkills { get; set; } 
} 
+0

Mylicie wpisy indeksu z wynikami indeksu. Podaj swoją klasę 'PositionSearchResultModel', a ja odpowiem kompletnym rozwiązaniem. Dzięki. –

+0

Dodano mój model widoku. – Jamez

+0

Widzę, że próbujesz oznaczyć to pole jako analizowane. Czy chcesz dokładnego dopasowania nazwy umiejętności? A może chcesz przeprowadzić analizowane wyszukiwanie? –

Odpowiedz

8

Ponieważ chcesz zrobić analizowanego przeszukiwanie przed nazwą umiejętności, trzeba odizolować go jako oddzielny wpis indeksu.

public class PositionSearch 
    : AbstractIndexCreationTask<Employer, PositionSearchResultModel> 
{ 
    public PositionSearch() 
    { 
     Map = employers => 
       from employer in employers 
       from position in employer.Positions 
       select new 
       { 
        EmployerId = employer.Id, 
        EmployerName = employer.Name, 
        PositionId = position.Id, 
        PositionTitle = position.Title, 
        position.Location, 
        position.Description, 
        position.RequiredSkills, 

        // Isolate the search property into it's own value 
        SkillsSearch = position.RequiredSkills.Select(x => x.Skill) 
       }; 

     // you could store all fields if you wanted, but the search field 
     // doesn't need to be stored so that would be wasteful. 
     Store(x => x.PositionId, FieldStorage.Yes); 
     Store(x => x.PositionTitle, FieldStorage.Yes); 
     Store(x => x.Location, FieldStorage.Yes); 
     Store(x => x.Description, FieldStorage.Yes); 
     Store(x => x.RequiredSkills, FieldStorage.Yes); 

     // Any field you are going to use .Search() on should be analyzed. 
     Index(x => x.SkillsSearch, FieldIndexing.Analyzed); 
    } 
} 

Uwaga: Podałem prognozę jako wynik indeksu. To jest cukier składniowy. Nie jest źle, aby go opuścić, ale musisz określić swoje pole wyszukiwania za pomocą ciągu znaków.

Będziesz również dodać pole wyszukiwania do swojej klasie wyniki

public string[] SkillsSearch { get; set; } 

To naprawdę nie ma znaczenia, jakiego typu jest. Tablica ciągów lub kolekcja będzie działać dobrze. Możesz także użyć tylko łańcucha lub obiektu, ponieważ jest to tylko nazwa, która jest istotna.

Podczas kwerendy przeciwko tym indeksie, należy użyć metody .Search(), tak:

var results = session.Query<PositionSearchResultModel, PositionSearch>() 
    .Customize(x => x.WaitForNonStaleResults()) // only use this in testing 
    .Search(x=> x.SkillsSearch, "SkillName") 
    .ProjectFromIndexFieldsInto<PositionSearchResultModel>() // AsProjection would also work 
    .ToList(); 

Należy zauważyć, że jedynym powodem, trzeba przechowywać tak wiele pól jest ponieważ chcesz ich projektu. Jeśli podzielisz pozycje na ich własne dokumenty, będziesz miał znacznie mniejsze indeksy, a tym bardziej projekt. Należy pamiętać, że podczas projektowania wszystkie pola w oryginalnym dokumencie już istnieją i pochodzą bezpośrednio ze składnicy dokumentów, a nie muszą być kopiowane do indeksu. Jeśli więc twoje oryginalne dokumenty bardziej pasują do pożądanych rezultatów, to masz mniej pracy do wykonania.

+0

Potrzebuję zrobić coś podobnego do tego, ale nie muszę oglądać wyniku, wystarczy sprawdzić, czy Umiejętność jest obecna. Czy to oznacza, że ​​nie muszę przechowywać tych pól? – codedog

+1

@DanyW - Jeśli używasz tylko pól w klauzuli where, nie musisz ich zapisywać. Należy je zapisać tylko wtedy, gdy zamierzasz wyświetlać je z powrotem do zestawu wyników. –

Powiązane problemy