Pluck id's from mongo query result - mongodb

I have the following query on mongo console
db.photos.find({'creation_date': {$gte: <somedate>)}}).
Is there a way to pluck the id's from query result just by using mongo shell ?

Try using the map() cursor method
var ids = db.photos.find({'creation_date': { '$gte': <somedate>) } }, {'_id': 1})
.map(function (doc){ return doc._id; })
You can also use the distinct() method as
var ids = db.photos.distinct('_id', {'creation_date': { '$gte': <somedate>) } })
or with the toArray() cursor method on aggregate() as
var ids = db.photos.aggregate([
{ '$match': {'creation_date': { '$gte': <somedate>) } } }
{ '$group': { '_id': 0, 'ids': { '$push': '$_id' } } }
]).toArray()[0].ids

MongoDb provides limit fields from query results
See more about in below link
http://docs.mongodb.org/manual/tutorial/project-fields-from-query-results/
db.photos.find({'creation_date': {$gte: )},{"_id":1}});
returns
{
"_id":1
}
{
"-id":2
}
...

You can use distinct instead of find:
collection.distinct('_id', {'creation_date': some_date})

Related

mongodb: $substr inside $group

I am a bit new to mongodb, and I have a situation.
The entries in my mongodb collection is around 300k, I used mongodb aggregate to migrate all the old entries to new and my code looks like
collection.aggregate([
{ $group: {
_id: "$_id",
"new_id" : {$substr : [{$first: "$old_id"}, 2,-1]}, //error exists here
"new_roles": {$push: "$old_role"},
}
},
{ $out: newCollection}
], {allowDiskUse:true}, function (updateError, updateResult) {
if (!updateError) {
return cb(false, true);
} else {
return cb(true, false);
}
})
What I want to achieve it that I want to take substring of old_id and put it in new_id. The old_id of old collection looks like a-112 a-34311. I want to remove a- from these old ids and put it into new id.
I tried using the above code but it shows error that The $substr accumulator is a unary operator. I tried searching for the error but no luck
You can't use $substr in the $group stage as it is not an accumulator operator. You need to do this in a $project stage like this:
collection.aggregate([
{ $group: {
_id: "$_id",
"new_id" : {$first: "$old_id"},
"new_roles": {$push: "$old_role"},
}
},
{$project: {
"new_id": {$substr: ["$new_id", 2, -1]},
"new_roles": 1
}
},
{ $out: newCollection}
], {allowDiskUse:true}, function (updateError, updateResult) {
if (!updateError) {
return cb(false, true);
} else {
return cb(true, false);
}
})

How to perform aggregate query with where condition

I have this MongoDB query:
var array=[]; //some string values
collection.aggregate(
{ $match: { '_id': { $in : array } } }
)
But this is not returning any results. How do I perform this?
As noted in the comments, your array variable is an array of hex string values ex :["57f36e94517f72bc09ee761e"] and for mongo shell, you need to first cast those string values to ObjectIds. Use the JavaScript map()
method to accomplish the casting in a list.
For example:
mongo shell
var array = ["585808969e39db5196444c07", "585808969e39db5196444c06"];
var ids = array.map(function(id){ return ObjectId(id); });
which you can then query using the aggregate function as in the following
db.collection.aggregate([
{ "$match": { "_id": { "$in" : ids } } }
])
The above is essentially the same as
db.collection.find({ "_id": { "$in": ids } })
Node.js
var {ObjectId} = require('mongodb'); // or ObjectID
var ids = array.map(id => ObjectId.isValid(id) ? new ObjectId(id) : null;);

How do I forEach on runCommand result

I got E QUERY TypeError: Object [object Object] has no method 'forEach'
How could I for each the result ?
cur = db[source_collection].runCommand('aggregate',
pipeline: pipeline
allowDiskUse: true)
cur.forEach (customer) ->
db[output_collection].update({'_id': customer._id},{
'$pull': {
'$records.items': {
$regex: /\s+/
}
}
})
Use the aggregate() helper instead since in 2.6 and later, the aggregate() helper always returns a cursor:
cur = db[source_collection].aggregate pipeline
cur.forEach (customer) ->
db[output_collection].update('_id': customer._id,
'$pull':
'records.$.items':
'$regex': /\s+/
)
As per mongo aggregation runCommand documentation
Using the aggregate command to return a cursor is a low-level operation, intended for authors of drivers.
and
runCommand returns a document that contains results
so you write cur.result.forEach
It is old but even though I will right this:
For the first case I think it will help:
cur.result.forEach(
function(doc)
{
...
...
})
I have more one that can I add more for future questions around it:
db.runCommand(
{ aggregate: "MyCollectionName",
pipeline: [
{ $group :
{
_id : "$GroupColumnName"
,"count": { "$sum": 1 }
, AllDocs: { $push: "$$ROOT" }
}
},
{ "$match": {"_id" :{ "$ne" : null } , "count" : {"$gt": 1} } }
],
allowDiskUse: true
}
).result.forEach(
function(doc)
{
doc.AllDocs.forEach(
function(docInternal)
{
print(docInternal._id);
}
);
})

Mongodb - aggregation of subdocument and update with the result

I have the following problem. I have found and summarized each value in a subdocument.
It gives the following [ { _id: 551fb140e4b04589d8997213, sumOfpeople: 342 } ]
I want to take the sumOfpeople and insert it to the same House( the same req.params.house_id)
House.aggregate([
{ $match: {
id: req.params.house_id
}},
{ $unwind: '$people' }, // unwind creates a doc for every array element
{ $group: {
_id: '$_id',
sumOfpeople: { $sum: '$people.nr'}
}}
], function (err, result) {
if (err) {
console.log(err);
return;
}
console.log(result);
});
This is the model that I want insert the result after the aggregation into.
module.exports = mongoose.model('House', {
id: String,
people: [{
id: String,
nr: Number
}],
sumOfpeople: Number //this is the field that I want to update after the aggregation
});
I have tried to use $set : {sumOfpeople: { $sum: '$people.nr'}}.
Is it possible to use $set inside an aggregation, or how can it be solved otherwise?
There's no way in MongoDB to write results directly into an existing document while doing an aggregation.
You've got 2 options:
retrieve the results in your application code, and then in a second query update the document.
use the $out operator, that will write the results of the aggregation into a new collection. This operation will delete all documents in the results collection and insert the new one. ( http://docs.mongodb.org/manual/reference/operator/aggregation/out/ )

Update multiple documents by id set. Mongoose

I wonder if mongoose has some method to update multiple documents by id set. For example:
for (var i = 0, l = ids.length; i < l; i++) {
Element.update({'_id': ids[i]}, {'visibility': visibility} ,function(err, records){
if (err) {
return false;
} else {
return true;
};
});
};
What i want to know, that if mongoose can do something like this:
Element.update({'_id': ids}, {'visibility': visibility}, {multi: true} ,function(err, records){
if (err) {
return false;
}
});
where ids is an array of ids, like ['id1', 'id2', 'id3'] - sample array.
Same question for find.
Most probably yes. And it is called using $in operator in mongodb query for update.
db.Element.update(
{ _id: { $in: ['id1', 'id2', 'id3'] } },
{ $set: { visibility : yourvisibility } },
{multi: true}
)
All you need is to find how to implement $in in mongoose.
in updateMany function no need of { multi: true }
db.collectionName.updateMany(
{
_id:
{
$in:
[
ObjectId("your object id"),
ObjectId("your object id")
]
}
},
{
$inc: { quantity: 100 }
})
I want to add one more point, you can use $in to fetch multiple document
db.collectionName.find(
{
_id:
{
$in:
[
ObjectId("your object id"),
ObjectId("your object id")
]
}
})
Updates all documents that match the specified filter for a collection.
let ids = ["kwwe232244h3j44jg3h4", "23h2u32g2h3b3hbh", "fhfu3h4h34u35"];
let visibility = true;
Element.updateMany({_id: {$in: ids}},
{ $set: { visibility } },
{multi: true} ,
function(err, records){
if (err) {
return false;
}
});
know more