Mongoose, limit each element of array result - javascript

To find objects with array of ids we can do this:
var idsArray = ['id1', 'id2', 'id3'];
SomeObject.find({'chatroomId': { $in: idsArray}}).exec();
.then(function(someObjects) {
console.log(someObjects);
})
Is it possible to limit result for each member in array?
Not for whole result like this:
SomeObject.find({'chatroomId': { $in: idsArray}}).limit(3)
but for each element. Maybe something like this:
SomeObject.find({'chatroomId': { $in: idsArray.forEach.limit(3)}});

Considering that you have a document structure like :
{
_id : ObjectId("591931855d0aad80c996eab2)",
chatName : 'SchoolChat',
chatrootId : ['id1', 'id2','id3','id4','id5']
}
You can use following query to get what you need :
db.collection_name.aggregate([
{ $unwind : '$chatrootId' },
{ $limit : 3},
{ $group : {
_id : '$_id',
chatName : { $first : '$chatName' },
chatroomId : { $push : '$chatrootId' },
}
}
]);
It will give you :
{
"_id" : ObjectId("591931855d0aad80c996eab2"),
"chatName" : "SchoolChat",
"chatroomId" : [ 'id1', 'id2', 'id3']
}

Related

nodejs how to dynamically manipulate your MongoDB aggregate in your controller?

I have a very loooong aggregate in my nodejs controller:
agentSaleModel.aggregate([
{
$match: {
$and:
[{
_id: { $in: req.body.propertyID },
active : true
}]
}
}, etc....
And it works great when I got elements in my req.body.propertyID
like ["property01","property02"] etc...
My problem is that I also want the aggregate to work when there are nothing in req.body.propertyID. (when its blank) - and then get all records.
This does not work:
agentSaleModel.aggregate([
{
$match: {
$and:
[{
_id: { $in: '' },
active : true
}]
}
}, etc....
So rather than doing an "if" with two huge sets of almost identical code:
if (req.body.propertyID) {
...the entire aggregate...
} else {
...the entire aggregate minus the _id: { $in: req.body.propertyID },...
}
Is there a smarter way to do this?
SOLUTION!! Thanks to FluffyNights :)
if (req.body.propertyID!='') {
var matchStr = {
$match: {
$and:
[{
_id: { $in: req.body.propertyID },
active : true
}]
}
}
} else {
var matchStr = {
$match: {
active : true
}
}
}
agentSaleModel.aggregate([ matchStr, etc..... (rest of pipeline)
you could do it like this:
let query = [
{
$match: {
$and:
[{
active : true
}]
}
}];
if(req.body.propertyID) {
query[0]["$match"]["$and"][0]["_id"] = { $in: req.body.propertyID };
}
agentSaleModel.aggregate(query, ...)
you could also use regex, like:
if(!req.body.properyID){
req.body.propertyID = [ ".*" ];
}
agentSaleModel.aggregate([
{
$match: {
$and:
[{
_id: { $in: req.body.propertyID },
active : true
}]
}
}, etc....
however, this might get slow.
Im not sure if passing null to $in would work the way you want, you could try it though.
What about trying to construct query before running it.
For example.
var query = req.body.propertyID ? { $and: [{_id: { $in: req.body.propertyID }, active : true}]} : {active : true}
agentSaleModel.aggregate([
{
$match: query
}, etc....
Hope this helps.
Here's an inline solution using computed property names:
$match: {
$and: [
{
_id: { [ req.body.propertyID ? '$in' : '$exists' ] : req.body.propertyID || true },
active: true,
},
],
}
When req.body.propertyID exists, the query becomes:
_id : { $in : req.body.propertyID }
If not:
_id : { $exists : true }
EDIT: this will also allow req.body.propertyID to equal "ALL" if you explicitly want to match all documents:
let selectAll = ! req.body.propertyID || req.body.propertyID === 'ALL';
const query = {
$match: {
$and: [
{
_id: { [ selectAll ? '$exists' : '$in' ] : selectAll || req.body.propertyID },
active: true,
},
],
},
};

Find element in an array that may or may not exist

I have a document that looks a bit like this:
> db.orders.find()
{
_id: ObjectId(),
_reminders: [{
notified: true,
timestamp: ISODate(),
completed: false
}]
}
{
_id: ObjectId(),
_reminders: []
}
What I am trying to find is a document in the orders collection where the "reminders" does not contain a reminder in a specific time range, and is not completed.
db.orders.find({
'_reminders': {
$elemMatch: {
completed: false,
timestamp: { $ne: time }
}
}
});
The problem is that this will not find an order which does not have any reminders at all.
How would one query this?
This should get you what you want
db.getCollection('Clock').find({
$or : [
{
_reminders : {
$elemMatch : {
timestamp : {
$lte : ISODate("2019-07-12T15:35:32.278Z"),
$gte : ISODate("2012-07-12T15:35:32.278Z")
},
completed : false
}
}
},
{
_reminders : {$size : 0}
},
{
_reminders : {$exists : false}
}
]
})
you should use $or query.
db.orders.find({$or: [ { _reminders: [] }, here_put_your_query_with_time_match ]}) - it will return both documents which match your query and these with empty _reminders

Sort collections of docs By the biggest embedded Doc with mongodb

I have this schema with mongoose
schema = new Schema({
id: {
type: String,
},
embedded: [embeddedSchema]
});
embeddedSchema = new Schema({
value: {
type: String,
},
});
This can produce something like :
{
"_id" : ObjectId("5454f4f1073cc3b529320f79"),
"embedded" : [
{
"value" : 123,
} , {
"value" : 123,
},
{
"value" : 123423,
}
]
}
/* 1 */
{
"_id" : ObjectId("5454f508910ef3b82970f11d"),
"embedded" : [
{
"value" : 1,
} , {
"value" : 2,
},
{
"value" : 9999999,
}]
}
I would like to sort the schema collection by the biggest value of embedded doc.
Which query can produce this kind of result ?
Thanks you!
When you sort descending on an array element field like value, MongoDB uses the maximum value of that field among all elements in the array.
So in this case it would be:
MyModel.find().sort('-embedded.value').exec(callback);

MongoDB insert record issue

I have a Mongo DB structure which looks something like this :
db.users.find().pretty();
{
"_id" : ObjectId("52b42b148ffa91f7ebbe8ebc"),
"username" : "test",
"password" : "test",
"party" : [
"4988",
"5037"
],
"something" : [
"3571"
],
"ludilo" : [],
}
Im using express js in my app and this module for connecting to Mongo https://npmjs.org/package/mongodb ,
How can I insert one entry into "something" array for user with id that I get from session.
I tried something like this , but with no success
var collection = db.collection('users');
collection.find({'_id':new ObjectID(req.user.id)}).toArray(function(err, items) {
console.dir(items);
}).insert({"something":"1234"});
You can $push a value to an array with
db.users.update(
{ _id: ObjectId( "52b42b148ffa91f7ebbe8ebc" ) },
{ $push: { something: "1234" } }
)
or if you do not want any duplicates in your array you can use $addToSet
db.users.update(
{ _id: ObjectId( "52b42b148ffa91f7ebbe8ebc" ) },
{ $addToSet: { something: "1234" } }
)
You can try this code:
collection.find({_id: new ObjectID(req.user.id)}).toArray(function(err, items) {
var doc = items[0];
doc.something.push('1234');
collection.update({_id: doc._id}, {$set: {something: doc.something}}, {safe: true}, function() {
//your next actions
});
});
I run this code on my local machine and it seems to work fine

MongoDB, remove object from array

Doc:
{
_id: 5150a1199fac0e6910000002,
name: 'some name',
items: [{
id: 23,
name: 'item name 23'
},{
id: 24,
name: 'item name 24'
}]
}
Is there a way to pull a specific object from an array? I.E. how do I pull the entire item object with id 23 from the items array.
I have tried:
db.mycollection.update({'_id': ObjectId("5150a1199fac0e6910000002")}, {$pull: {id: 23}});
However I am pretty sure that I am not using 'pull' correctly. From what I understand pull will pull a field from an array but not an object.
Any ideas how to pull the entire object out of the array.
As a bonus I am trying to do this in mongoose/nodejs, as well not sure if this type of thing is in the mongoose API but I could not find it.
try..
db.mycollection.update(
{ '_id': ObjectId("5150a1199fac0e6910000002") },
{ $pull: { items: { id: 23 } } },
false, // Upsert
true, // Multi
);
I have a document like
I have to delete address from address array
After searching lots on internet I found the solution
Customer.findOneAndUpdate(query, { $pull: {address: addressId} }, (err, data) => {
if (err) {
return res.status(500).json({ error: 'error in deleting address' });
}
res.json(data);
});
my database:
{
"_id" : ObjectId("5806056dce046557874d3ab18"),
"data" : [
{ "id" : 1 },
{ "id" : 2 },
{ "id" : 3 }
]
}
my query:
db.getCollection('play_table').update({},{$pull:{"data":{"id":3}}},{multi:true}
output:
{
"_id" : ObjectId("5806056dce046557874d3ab18"),
"data" : [
{ "id" : 1 },
{ "id" : 2 }
]
}
You can try it also:
db.getCollection('docs').update({ },{'$pull':{ 'items':{'id': 3 }}},{multi:true})
For a single record in array:
db.getCollection('documents').update(
{ },
{'$pull':{ 'items':{'mobile': 1234567890 }}},
{new:true}
);
For a multiple records with same mobile number in array:
db.getCollection('documents').update(
{ },
{
$pull: {
items: { mobile: 1234567890 }
}
},
{ new:true, multi:true }
)
Use $pull to remove the data
return this.mobiledashboardModel
.update({"_id": args.dashboardId}, { $pull: {"viewData": { "_id": widgetId}}})
.exec()
.then(dashboardDoc => {
return {
result: dashboardDoc
}
});
Kishore Diyyana:
If you want to remove all elements including the key of the element attributes list.
Here is the example of mongoDB unset operator:
db.UM_PREAUTH_CASE.update(
{ 'Id' : 123}, { $unset: { dataElements: ""} } )
JSON Look like this:
{ "Id":123,"dataElements" : [ { "createdBy" : "Kishore Babu Diyyana", "createdByUserId" : 2020 }, { "createdBy" : "Diyyana Kishore", "createdByUserId" : 2021 } ] }

Categories

Resources