ravendb

Forma correcta de recuperar más de 128 documentos con RavenDB



ravendb vs mongodb (5)

El número de solicitudes por sesión es un concepto separado y luego el número de documentos recuperados por llamada. Las sesiones son de corta duración y se espera que tengan pocas llamadas emitidas.

Si obtiene más de 10 de cualquier cosa de la tienda (aún menos que la predeterminada de 128) para el consumo humano, entonces algo está mal o su problema requiere una reflexión diferente, entonces la carga de documentos de camiones proviene del almacén de datos.

La indexación de RavenDB es bastante sofisticada. Buen artículo sobre indexación here y facetas here .

Si necesita realizar una agregación de datos, cree un mapa de mapa / reducción que resulte en datos agregados, por ejemplo:

Índice:

from post in docs.Posts select new { post.Author, Count = 1 } from result in results group result by result.Author into g select new { Author = g.Key, Count = g.Sum(x=>x.Count) }

Consulta:

session.Query<AuthorPostStats>("Posts/ByUser/Count")(x=>x.Author)();

Sé que las variantes de esta pregunta se han preguntado anteriormente (incluso por mí), pero todavía no entiendo una o dos cosas sobre esto ...

Tenía entendido que uno podría recuperar más documentos que la configuración predeterminada de 128 haciendo esto:

session.Advanced.MaxNumberOfRequestsPerSession = int.MaxValue;

Y he aprendido que una cláusula WHERE debería ser un ExpressionTree en lugar de un Func, por lo que se trata como Queryable en lugar de Enumerable. Así que pensé que esto debería funcionar:

public static List<T> GetObjectList<T>(Expression<Func<T, bool>> whereClause) { using (IDocumentSession session = GetRavenSession()) { return session.Query<T>().Where(whereClause).ToList(); } }

Sin embargo, eso solo devuelve 128 documentos. ¿Por qué?

Tenga en cuenta, aquí está el código que llama al método anterior:

RavenDataAccessComponent.GetObjectList<Ccm>(x => x.TimeStamp > lastReadTime);

Si agrego Tomar (n), entonces puedo obtener tantos documentos como quiera. Por ejemplo, esto devuelve 200 documentos:

return session.Query<T>().Where(whereClause).Take(200).ToList();

En base a todo esto, parecería que la forma adecuada de recuperar miles de documentos es establecer MaxNumberOfRequestsPerSession y usar Take () en la consulta. ¿Está bien? Si no, ¿cómo se debe hacer?

Para mi aplicación, necesito recuperar miles de documentos (que contienen muy poca información). Mantenemos estos documentos en la memoria y los usamos como fuente de datos para los gráficos.

** EDIT **

Intenté usar int.MaxValue en mi Take ():

return session.Query<T>().Where(whereClause).Take(int.MaxValue).ToList();

Y eso devuelve 1024. Argh. ¿Cómo obtengo más de 1024?

** EDIT 2 - Ejemplo de documento que muestra datos **

{ "Header_ID": 3525880, "Sub_ID": "120403261139", "TimeStamp": "2012-04-05T15:14:13.9870000", "Equipment_ID": "PBG11A-CCM", "AverageAbsorber1": "284.451", "AverageAbsorber2": "108.442", "AverageAbsorber3": "886.523", "AverageAbsorber4": "176.773" }


La función Take(n) solo le dará hasta 1024 de forma predeterminada. Sin embargo, puede cambiar este valor predeterminado en Raven.Server.exe.config :

<add key="Raven/MaxPageSize" value="5000"/>

Para obtener más información, consulte: http://ravendb.net/docs/intro/safe-by-default


La función Tomar (n) solo le dará hasta 1024 de forma predeterminada. Sin embargo, puede usarlo en par con Omitir (n) para obtener todos

var points = new List<T>(); var nextGroupOfPoints = new List<T>(); const int ElementTakeCount = 1024; int i = 0; int skipResults = 0; do { nextGroupOfPoints = session.Query<T>().Statistics(out stats).Where(whereClause).Skip(i * ElementTakeCount + skipResults).Take(ElementTakeCount).ToList(); i++; skipResults += stats.SkippedResults; points = points.Concat(nextGroupOfPoints).ToList(); } while (nextGroupOfPoints.Count == ElementTakeCount); return points;

Paginación de RavenDB


También puede utilizar un índice predefinido con el método Stream . Puede utilizar una cláusula Where en los campos indexados.

var query = session.Query<User, MyUserIndex>(); var query = session.Query<User, MyUserIndex>().Where(x => !x.IsDeleted); using (var enumerator = session.Advanced.Stream<User>(query)) { while (enumerator.MoveNext()) { var user = enumerator.Current.Document; // do something } }

Índice de ejemplo:

public class MyUserIndex: AbstractIndexCreationTask<User> { public MyUserIndex() { this.Map = users => from u in users select new { u.IsDeleted, u.Username, }; } }

Documentación: ¿Qué son los índices? Sesión: Consulta: ¿Cómo transmitir resultados de consulta?

Nota importante: el método Stream no rastreará objetos. Si cambia los objetos obtenidos de este método, SaveChanges() no será consciente de ningún cambio.

Otra nota: puede obtener la siguiente excepción si no especifica el índice a usar.

InvalidOperationException: StreamQuery no admite la consulta de índices dinámicos. Está diseñado para ser utilizado con grandes conjuntos de datos y es poco probable que devuelva todos los conjuntos de datos después de 15 segundos de indexación, como hace Query ().


Vale la pena señalar que desde la versión 2.5, RavenDB tiene una "API de resultados ilimitados" para permitir la transmisión. El ejemplo de la documentación muestra cómo usar esto:

var query = session.Query<User>("Users/ByActive").Where(x => x.Active); using (var enumerator = session.Advanced.Stream(query)) { while (enumerator.MoveNext()) { User activeUser = enumerator.Current.Document; } }

Hay soporte para consultas estándar de RavenDB, consultas de Lucence y también hay soporte asíncrono.

La documentación se puede encontrar here . El artículo introductorio del blog de Ayende se puede encontrar here .