2011-02-24 5 views
7

Estamos usando Raven para validar inicios de sesión para que las personas puedan ingresar a nuestro sitio.Consultar Raven con Where() solo filtros contra los primeros 128 documentos?

Lo que hemos encontrado es que si usted hace esto:

// Context is an IDocumentSession 
Context.Query<UserModels>() 
      .SingleOrDefault(u => u.Email.ToLower() == email.ToLower()); 

La consulta sólo filtros en los primeros 128 documentos de los documentos en Raven. Hay miles en nuestra base de datos, así que a menos que su correo electrónico esté en los primeros 128 devueltos, no tiene suerte.

Ninguno del código de ejemplo de Raven o cualquier código de muestra que he encontrado en la red realiza cualquier bucle usando Omitir() y tomar() para recorrer el conjunto.

  1. ¿Es este el comportamiento deseado de Raven?
  2. ¿Es el mismo comportamiento incluso si utiliza una consulta avanzada de Lucene? es decir; ¿Las consultas avanzadas se comportan de forma diferente?
  3. ¿La solución a continuación es apropiada? Se ve un poco feo. : P

Mi solución es recorrer el conjunto de todos los documentos hasta que I encuentre un resultado no nulo, luego lo rompo y lo devuelvo.

public T SingleWithIndex(string indexName, Func<T, bool> where) 
{ 
    var pageIndex = 1; 
    const int pageSize = 1024; 
    RavenQueryStatistics stats; 

var queryResults = Context.Query<T>(indexName) 
    .Statistics(out stats) 
    .Customize(x => x.WaitForNonStaleResults()) 
    .Take(pageSize) 
    .Where(where).SingleOrDefault(); 

if (queryResults == null && stats.TotalResults > pageSize) 
{ 
    for (var i = 0; i < (stats.TotalResults/(pageIndex * pageSize)); i++) 
    { 
     queryResults = Context.Query<T>(indexName) 
      .Statistics(out stats) 
      .Customize(x => x.WaitForNonStaleResults()) 
      .Skip(pageIndex * pageSize) 
      .Take(pageSize) 
      .Where(where).SingleOrDefault(); 

     if (queryResults != null) break; 

     pageIndex++; 
    } 

} 

return queryResults; 

}

EDIT:

uso de la corrección a continuación no está pasando Parámetros de consulta a mi ejemplo RavenDB. Aún no estoy seguro de por qué.

Context.Query<UserModels>() 
    .Where(u => u.Email == email) 
    .SingleOrDefault(); 

Al final estoy usando la sintaxis de Lucene avanzada en lugar de las consultas de linq y todo está funcionando como se esperaba.

Respuesta

4

RavenDB no entiende SingleOrDefault, por lo que realiza una consulta sin el filtro. Su condición se ejecuta en el conjunto de resultados, pero por defecto Raven solo devuelve los primeros 128 documentos. En su lugar, usted tiene que llamar

Context.Query<UserModels>() 
     .Where(u => u.Email == email) 
     .SingleOrDefault(); 

por lo que el filtrado se realiza por RavenDB/Lucene.

+0

He publicado esto en el grupo de google y Ayende mencionó que aún no admiten un predicado en SingleOrDefault(). Mi problema es que la consulta de linq no pasa un parámetro de consulta a mi servidor. –

Cuestiones relacionadas