2013-08-21 2 views
1

j'ai les deux définitions de classes suivantes:RavenDB l'index de requête

public class Location : Doc 
{ 
    public string Country { get; set; } 
    public string Region { get; set; } 
    public string City { get; set; } 
    public string PostalCode { get; set; } 
    public Double Latitude { get; set; } 
    public Double Longitude { get; set; } 
    public string MetroCode { get; set; } 
    public string AreaCode { get; set; } 
    public List<IpRange> IpRanges { get; set; } 
} 

et

public class IpRange 
{ 
    public long Start { get; set; } 
    public long End { get; set; } 
} 

J'ai un index défini comme suit:

public class Locations_ByRange : AbstractIndexCreationTask<Location> 
{ 
    public Locations_ByRange() 
    { 
     Map = locations => 
      from location in locations 
      from range in location.IpRanges 
      select new 
      { 
       range.Start, 
       range.End 
      }; 
    } 
} 

J'essaie alors d'interroger l'indice est le suivant:

var queryable = DocumentSession.Query<IpRange, Locations_ByRange>() 
         .FirstOrDefault(x => x.Start <= reverseIp && x.End >= reverseIp) ?? new IpRange(); 

Mais, je suis rencontré l'erreur suivante lors de l'exécution de la requête:

Exception Details: System.InvalidCastException: Unable to cast object of type 'Jodolo.Data.Locations.Location' to type 'Jodolo.Data.Locations.IpRange'. 

Et, voici le StackTrace:

[InvalidCastException: Unable to cast object of type 'Jodolo.Data.Locations.Location' to type 'Jodolo.Data.Locations.IpRange'.] 
    Raven.Client.Document.InMemoryDocumentSessionOperations.TrackEntity(String key, RavenJObject document, RavenJObject metadata, Boolean noTracking) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\InMemoryDocumentSessionOperations.cs:357 
    Raven.Client.Document.SessionOperations.QueryOperation.Deserialize(RavenJObject result) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\SessionOperations\QueryOperation.cs:167 
    System.Linq.WhereSelectListIterator`2.MoveNext() +104 
    System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) +381 
    System.Linq.Enumerable.ToList(IEnumerable`1 source) +58 
    Raven.Client.Document.SessionOperations.QueryOperation.Complete() in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\SessionOperations\QueryOperation.cs:143 
    Raven.Client.Document.AbstractDocumentQuery`2.GetEnumerator() in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\AbstractDocumentQuery.cs:891 
    System.Linq.Enumerable.FirstOrDefault(IEnumerable`1 source) +152 
    Raven.Client.Linq.RavenQueryProviderProcessor`1.GetQueryResult(IDocumentQuery`1 finalQuery) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Linq\RavenQueryProviderProcessor.cs:1529 
    Raven.Client.Linq.RavenQueryProviderProcessor`1.ExecuteQuery() in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Linq\RavenQueryProviderProcessor.cs:1454 
    Raven.Client.Linq.RavenQueryProviderProcessor`1.Execute(Expression expression) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Linq\RavenQueryProviderProcessor.cs:1427 
    Raven.Client.Linq.RavenQueryProvider`1.Execute(Expression expression) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Linq\RavenQueryProvider.cs:155 
    Raven.Client.Linq.RavenQueryProvider`1.System.Linq.IQueryProvider.Execute(Expression expression) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Linq\RavenQueryProvider.cs:198 
    System.Linq.Queryable.FirstOrDefault(IQueryable`1 source, Expression`1 predicate) +287 

. . .

Je suis un peu heureux de voir cela, car finalement j'essaye de récupérer le document de localisation qui satisfait les paramètres de requête. Il est clair que je peux changer la déclaration de type sur l'appel de requête à

.Query<Location, Locations_ByRange>() 

Mais, je puis mal à comprendre comment interroger les champs stockés dans l'index; car il n'y a pas de champs Start et End définis pour un objet Location.

Toute aide avec ceci serait grandement appréciée.

Répondre

1

Changer votre requête:

using Raven.Client; 

... 

var location = session.Query<IpRange, Locations_ByRange>() 
         .Where(x => x.Start <= reverseIp && x.End >= reverseIp) 
         .As<Location>() 
         .FirstOrDefault(); 

Dans votre index, vous devrez peut-être ajouter des notes de tri:

public class Locations_ByRange : AbstractIndexCreationTask<Location, IpRange> 
{ 
    public Locations_ByRange() 
    { 
     Map = locations => 
      from location in locations 
      from range in location.IpRanges 
      select new 
      { 
       range.Start, 
       range.End 
      }; 

     Sort(x => x.Start, SortOptions.Long); 
     Sort(x => x.End, SortOptions.Long); 
    } 
} 

Notez que j'ai ajouté le type de retour en haut à AbstractIndexCreationTask<Location, IpRange>. Cela permettra d'aligner les types afin que la méthode Sort puisse localiser ces propriétés.

+0

Je ne peux pas construire si je change simplement la requête comme vous l'avez spécifié. Y a-t-il une déclaration d'utilisation que je dois ajouter à la classe? –

+0

J'ai ajouté une directive using pour Raven.Client.Linq, mais toujours pas de chance. Hmmm ... –

+0

Voir ma réponse mise à jour sur la façon de modifier l'index pour ajouter des conseils de tri. Sans eux, ces champs sont probablement triés par ordre de chaînes et rejetant la requête de plage. –