que - mongodb español
mongodb obtiene registros distintos (5)
Creo que puedes usar agregado como este
collection.aggregate({
$group : {
"_id" : "$id",
"docs" : {
$first : {
"name" : "$name",
"ttm" : "$ttm",
"val" : "$val",
}
}
}
});
Estoy usando mongoDB
en el que tengo una colección del siguiente formato.
{"id" : 1 , name : x ttm : 23 , val : 5 }
{"id" : 1 , name : x ttm : 34 , val : 1 }
{"id" : 1 , name : x ttm : 24 , val : 2 }
{"id" : 2 , name : x ttm : 56 , val : 3 }
{"id" : 2 , name : x ttm : 76 , val : 3 }
{"id" : 3 , name : x ttm : 54 , val : 7 }
En esa colección he consultado para obtener registros en orden descendente como este:
db.foo.find({"id" : {"$in" : [1,2,3]}}).sort(ttm : -1).limit(3)
Pero da dos registros de la misma id = 1
y quiero registros que den 1 registro por id
.
¿Es posible en mongodb?
Desea usar la agregación. Podrías hacer eso así:
db.test.aggregate([
// each Object is an aggregation.
{
$group: {
originalId: {$first: ''$_id''}, // Hold onto original ID.
_id: ''$id'', // Set the unique identifier
val: {$first: ''$val''},
name: {$first: ''$name''},
ttm: {$first: ''$ttm''}
}
}, {
// this receives the output from the first aggregation.
// So the (originally) non-unique ''id'' field is now
// present as the _id field. We want to rename it.
$project:{
_id : ''$originalId'', // Restore original ID.
id : ''$_id'', //
val : ''$val'',
name: ''$name'',
ttm : ''$ttm''
}
}
])
Esto será muy rápido ... ~ 90ms para mi DB de prueba de 100,000 documentos.
Ejemplo:
db.test.find()
// { "_id" : ObjectId("55fb595b241fee91ac4cd881"), "id" : 1, "name" : "x", "ttm" : 23, "val" : 5 }
// { "_id" : ObjectId("55fb596d241fee91ac4cd882"), "id" : 1, "name" : "x", "ttm" : 34, "val" : 1 }
// { "_id" : ObjectId("55fb59c8241fee91ac4cd883"), "id" : 1, "name" : "x", "ttm" : 24, "val" : 2 }
// { "_id" : ObjectId("55fb59d9241fee91ac4cd884"), "id" : 2, "name" : "x", "ttm" : 56, "val" : 3 }
// { "_id" : ObjectId("55fb59e7241fee91ac4cd885"), "id" : 2, "name" : "x", "ttm" : 76, "val" : 3 }
// { "_id" : ObjectId("55fb59f9241fee91ac4cd886"), "id" : 3, "name" : "x", "ttm" : 54, "val" : 7 }
db.test.aggregate(/* from first code snippet */)
// output
{
"result" : [
{
"_id" : ObjectId("55fb59f9241fee91ac4cd886"),
"val" : 7,
"name" : "x",
"ttm" : 54,
"id" : 3
},
{
"_id" : ObjectId("55fb59d9241fee91ac4cd884"),
"val" : 3,
"name" : "x",
"ttm" : 56,
"id" : 2
},
{
"_id" : ObjectId("55fb595b241fee91ac4cd881"),
"val" : 5,
"name" : "x",
"ttm" : 23,
"id" : 1
}
],
"ok" : 1
}
PROS: Casi seguro el método más rápido.
CONTRAS: Implica el uso de la complicada API de agregación. Además, está estrechamente relacionado con el esquema original del documento. Sin embargo, es posible generalizar esto.
El problema es que desea destilar 3 registros coincidentes hasta uno sin proporcionar ninguna lógica en la consulta sobre cómo elegir entre los resultados coincidentes.
Sus opciones son básicamente especificar la lógica de agregación de algún tipo (seleccione el valor máximo o mínimo para cada columna, por ejemplo), o ejecutar una consulta de selección distinta y solo seleccionar los campos que desea que sean distintos.
querymongo.com hace un buen trabajo al traducir estas distintas consultas por usted (de SQL a MongoDB).
Por ejemplo, este SQL:
SELECT DISTINCT columnA FROM collection WHERE columnA > 5
Se devuelve como este MongoDB:
db.runCommand({
"distinct": "collection",
"query": {
"columnA": {
"$gt": 5
}
},
"key": "columnA"
});
Hay un comando distinct
en mongodb, que puede usarse junto con una consulta. Sin embargo, creo que esto solo devuelve una lista distinta de valores para una clave específica que usted nombra (es decir, en su caso, solo obtendría los valores de identificación devueltos), así que no estoy seguro de que esto le proporcione exactamente lo que desea si necesita todos los documentos; en su lugar, puede necesitar MapReduce.
Documentación en distinct: http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct
Si desea escribir el resultado distinto en un archivo usando javascript ... así es como lo hace
cursor = db.myColl.find({''fieldName'':''fieldValue''})
var Arr = new Array();
var count = 0;
cursor.forEach(
function(x) {
var temp = x.id;
var index = Arr.indexOf(temp);
if(index==-1)
{
printjson(x.id);
Arr[count] = temp;
count++;
}
})