sql >> Base de Datos >  >> NoSQL >> MongoDB

Cursor de agregación Mongo y conteo

Es posible que esto merezca una explicación completa para aquellos que puedan buscarlo, por lo que se agregará una para la posteridad.

Específicamente, lo que se devuelve es un flujo de eventos para node.js que envuelve efectivamente el stream.Readable interfaz con un par de métodos de conveniencia. Un .count() no es uno de ellos en la actualidad y teniendo en cuenta la interfaz actual utilizada no tendría mucho sentido.

Similar al resultado devuelto por .stream() método disponible para los objetos del cursor, un "recuento" no tendría mucho sentido aquí cuando considere la implementación, ya que está destinado a procesarse como un "flujo" donde eventualmente llegará a un "final" pero de lo contrario solo desea procesar hasta llegar.

Si consideró la interfaz estándar de "Cursor" del controlador, hay algunas razones sólidas por las que el cursor de agregación no es el mismo:

  1. Los cursores permiten que las acciones "modificadoras" se procesen antes de su ejecución. Estos caen en las categorías de .sort() , .limit() y .skip() . Todos estos en realidad tienen directivas equivalentes en el marco de agregación que se especifican en la canalización. Como etapas de canalización que podrían aparecer "en cualquier lugar" y no solo como una opción de procesamiento posterior a una consulta simple, no tendría mucho sentido ofrecer el mismo procesamiento de "cursor".

  2. Otros modificadores de cursor incluyen especiales como .hint() , .min() y .max() que son alteraciones de la "selección de índices" y el procesamiento. Si bien estos podrían ser útiles para la canalización de agregación, actualmente no existe una forma sencilla de incluirlos en la selección de consultas. En su mayoría, la lógica del punto anterior anula cualquier punto de usar el mismo tipo de interfaz para un "Cursor".

Las otras consideraciones son lo que realmente quiere hacer con un cursor y por qué "quiere" que se devuelva uno. Dado que un cursor suele ser un "viaje de ida" en el sentido de que generalmente solo se procesan hasta que se alcanza un final y en "lotes" utilizables, entonces se llega a una conclusión razonable de que el "recuento" en realidad llega al final, cuando en realidad esa "cola" finalmente se agota.

Si bien es cierto que, de hecho, la implementación estándar del "cursor" tiene algunos trucos, la razón principal es que esto solo amplía un concepto de "metadatos", ya que el motor de creación de perfiles de consultas debe "escanear" una cierta cantidad de documentos para determinar qué elementos para devolver en el resultado.

Sin embargo, el marco de agregación juega un poco con este concepto. Dado que no solo hay los mismos resultados que se procesarían a través del generador de perfiles de consultas estándar, sino que también hay etapas adicionales. Cualquiera de estas etapas tiene el potencial de "modificar" el "recuento" resultante que en realidad se devolvería en el "flujo" para ser procesado.

Nuevamente, si desea ver esto desde un punto de vista académico y decir que "Claro, el motor de consulta debe mantener los 'metadatos' para el conteo, pero ¿no podemos rastrear lo que se modifica después?". Este sería un argumento justo, y operadores de tubería como $match y $group o $unwind y posiblemente incluso incluyendo $project y el nuevo $redact , todos podrían considerarse un caso razonable para mantener su propio seguimiento de los "documentos procesados" en cada etapa de la canalización y actualizarlos en los "metadatos" que posiblemente podrían devolverse para explicar el recuento total de resultados de la canalización.

El último argumento es razonable, pero considere también que en la actualidad la implementación de un concepto de "Cursor" para los resultados de la canalización de agregación es un nuevo concepto para MongoDB. Se podría argumentar con justicia que todas las expectativas "razonables" en el primer punto de diseño habrían sido que "la mayoría" de los resultados de la combinación de documentos no tendrían un tamaño que restringiera las limitaciones de BSON. Pero a medida que aumenta el uso, las percepciones se alteran y las cosas cambian para adaptarse.

Entonces, esto "podría" posiblemente cambiarse, pero no es así como se implementa "actualmente". Mientras que .count() en una implementación de cursor estándar tiene acceso a los "metadatos" donde se registra el número escaneado, cualquier método en la implementación actual daría como resultado la recuperación de todos los resultados del cursor, al igual que .itcount() hace en el caparazón.

Procese los elementos del "cursor" contando con el evento de "datos" y emitiendo algo (posiblemente un generador de flujo JSON) como el "recuento" al final. Para cualquier caso de uso que requiera un conteo "por adelantado", no parecería un uso válido para un cursor de todos modos, ya que seguramente la salida sería un documento completo de un tamaño razonable.