Finding a particular object in an array mongoDB - javascript

I have a collection that is composed of some strings, objects, and one array. Within that array are several objects. I am attempting to remove all of the orders with the object id of ObjectId("587ec66e5ed5cb0061092dbe"). See below for the schema and related data. I have tried everything under the sun.
var campgroundSchema = new mongoose.Schema({
name: String,
image: String,
description: String,
price: String,
author: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
username: String
},
orders: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Order"
}
]
});
Below is sample data.
{
"_id" : ObjectId("587ec65e5ed5cb0061092dbd"),
"name" : "is Forrest Cool?",
"price" : "",
"image" : "https://dsafd.com",
"description" : "",
"orders" :
[
ObjectId("587ec66e5ed5cb0061092dbe"),
ObjectId("587ec6bc5ed5cb0061092dc0"),
ObjectId("587ec6c05ed5cb0061092dc2"),
ObjectId("587ec7178f628931610636dc"),
ObjectId("587ec71e8f628931610636de")
],
"author" : { "id" : ObjectId("587ec6145ed5cb0061092dbc"),
"username" : "forrest" },
"__v" : 18
}
Thank you so much.

To find the specific element with particular ObjectId inside orders array, You can use $in.
Try this:
//orderObjectId is the object id you want to find inside orders.
Campground.find({orders : {$in : [orderObjectId]}},{'orders.$':1},function(err,result){
...
});
'orders.$':1 will return only that element from orders array
To delete that particular order,
//_id is optional, you can query using orderID also.
Campground.update({
_id :someObjectId, orders : {$in : [orderObjectId]}
},{
$pull : {order : orderObjectId}
},function(err,result){
...
});
Update:
Accroding to your comment, it seems you are having facing problem using this.
Try this:
//if you are receiving orderId as string, convert string to ObjectId
var orderId = mongoose.Schema.Types.ObjectId("587d78b8e898d1e732b3888a");
Campground.find({"orders": {$in : [orderId]}},function(err, result){
if(err){
console.log(err);
} else {
console.log("FOUND RESULT: " + result);
}
});
Hope this helps.

Related

How to add within an array information using findOneAndUpdate without deleting information that was previously contained [duplicate]

I am working on an express js application where I need to update a nested array.
1) Schema :
//Creating a mongoose schema
var userSchema = mongoose.Schema({
_id: {type: String, required:true},
name: String,
sensors: [{
sensor_name: {type: String, required:true},
measurements: [{time: String}]
}] });
2)
Here is the code snippet and explanation is below:
router.route('/sensors_update/:_id/:sensor_name/')
.post(function (req, res) {
User.findOneAndUpdate({_id:req.body._id}, {$push: {"sensors" :
{"sensor_name" : req.body.sensor_name , "measurements.0.time": req.body.time } } },
{new:true},function(err, newSensor) {
if (err)
res.send(err);
res.send(newSensor)
}); });
I am able to successfully update a value to the measurements array using the findOneAndUpdate with push technique but I'm failing when I try to add multiple measurements to the sensors array.
Here is current json I get if I get when I post a second measurement to the sensors array :
{
"_id": "Manasa",
"name": "Manasa Sub",
"__v": 0,
"sensors": [
{
"sensor_name": "ras",
"_id": "57da0a4bf3884d1fb2234c74",
"measurements": [
{
"time": "8:00"
}
]
},
{
"sensor_name": "ras",
"_id": "57da0a68f3884d1fb2234c75",
"measurements": [
{
"time": "9:00"
}
]
}]}
But the right format I want is posting multiple measurements with the sensors array like this :
Right JSON format would be :
{
"_id" : "Manasa",
"name" : "Manasa Sub",
"sensors" : [
{
"sensor_name" : "ras",
"_id" : ObjectId("57da0a4bf3884d1fb2234c74"),
"measurements" : [
{
"time" : "8:00"
}
],
"measurements" : [
{
"time" : "9:00"
}
]
}],
"__v" : 0 }
Please suggest some ideas regarding this. Thanks in advance.
You might want to rethink your data model. As it is currently, you cannot accomplish what you want. The sensors field refers to an array. In the ideal document format that you have provided, you have a single object inside that array. Then inside that object, you have two fields with the exact same key. In a JSON object, or mongo document in this context, you can't have duplicate keys within the same object.
It's not clear exactly what you're looking for here, but perhaps it would be best to go for something like this:
{
"_id" : "Manasa",
"name" : "Manasa Sub",
"sensors" : [
{
"sensor_name" : "ras",
"_id" : ObjectId("57da0a4bf3884d1fb2234c74"),
"measurements" : [
{
"time" : "8:00"
},
{
"time" : "9:00"
}
]
},
{
// next sensor in the sensors array with similar format
"_id": "",
"name": "",
"measurements": []
}],
}
If this is what you want, then you can try this:
User.findOneAndUpdate(
{ _id:req.body._id "sensors.sensor_name": req.body.sensor_name },
{ $push: { "sensors.0.measurements": { "time": req.body.time } } }
);
And as a side note, if you're only ever going to store a single string in each object in the measurements array, you might want to just store the actual values instead of the whole object { time: "value" }. You might find the data easier to handle this way.
Instead of hardcoding the index of the array it is possible to use identifier and positional operator $.
Example:
User.findOneAndUpdate(
{ _id: "Manasa" },
{ $push: { "sensors.$[outer].measurements": { "time": req.body.time } } }
{ "arrayFilters:" [{"outer._id": ObjectId("57da0a4bf3884d1fb2234c74")}]
);
You may notice than instead of getting a first element of the array I specified which element of the sensors array I would like to update by providing its ObjectId.
Note that arrayFilters are passed as the third argument to the update query as an option.
You could now make "outer._id" dynamic by passing the ObjectId of the sensor like so: {"outer._id": req.body.sensorId}
In general, with the use of identifier, you can get to even deeper nested array elements by following the same procedure and adding more filters.
If there was a third level nesting you could then do something like:
User.findOneAndUpdate(
{ _id: "Manasa" },
{ $push: { "sensors.$[outer].measurements.$[inner].example": { "time": req.body.time } } }
{ "arrayFilters:" [{"outer._id": ObjectId("57da0a4bf3884d1fb2234c74"), {"inner._id": ObjectId("57da0a4bf3884d1fb2234c74"}}]
);
You can find more details here in the answer written by Neil Lunn.
refer ::: positional-all
--- conditions :: { other_conditions, 'array1.array2.field_to_be_checked': 'value' }
--- updateData ::: { $push : { 'array1.$[].array2.$[].array3' : 'value_to_be_pushed' } }

Reference is working like Embed while Associating

I was learning Associations in MongoDB. There I learned how to use Embed, but while working on References, I got stuck for few days as its working same as Embed. Instead of showing just the ObjectId in the array, the whole object is being added to the array.
Here's the snippet,
campground schema:
var campgroundSchema = new mongoose.Schema({
name: String,
image: String,
description: String,
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Comment"
}
]
});
comment schema:
var commentSchema = mongoose.Schema({
text: String,
author: String
});
Models
var Campground = mongoose.model("Campground", campgroundSchema);
var Comment = mongoose.model("Comment", commentSchema);
Output:
{ "_id" : ObjectId("5a71970ec0379521607b5f47"), "comments" : ***[ { "_id" :
ObjectId("5a71970ec0379521607b5f4a"), "text" : "this place is gr8", "author"
: "Homer", "__v" : 0 } ]***, "name" : "Clould's Rest", "image" :
"https://farm7.staticflickr.com/6014/6015893151_044a2af184.jpg",
"description" : "blah blah", "__v" : 1 }
what I mean to say is instead of showing the whole object inside comments array, the array must show only the reference i.e ObjectId
like this
{ "_id" : ObjectId("5a71970ec0379521607b5f47"), "comments"
: ObjectId("5a71970ec0379521607b5f4a") ], "name" : "Clould's Rest", "image" :
"https://farm7.staticflickr.com/6014/6015893151_044a2af184.jpg",
"description" : "blah blah", "__v" : 1 }
that's how references work right?

Add to Collection if not found

I have an embedded document in my collection name as likes:
{
"_id" : ObjectId("57a31e18fa0299542ab8dd80"),
"created" : ISODate("2016-08-04T10:51:04.971Z"),
"likes" : [
{
"user" : ObjectId("1"),
"date" : 123
},
{
"user" : ObjectId("2"),
"date" : 456
}
],
"comments" : [],
"tag" : []
}
A User can like only one time. So there must be only one entry per User.
The problem is: It looks for date too in the object list, though I just want to search the user and add current date if entry not found. Because date differs every time and I get duplicated entries for same user.
Here is my mongoose query:
var likeObj = {
"user": "1", //user id
"date": Utils.getUnixTimeStamp() //date
};
post.update({_id: postId}, {$addToSet: {"likes": likeObj}} ,function(err,doc){
//success
});
You can add the user to the query:
post.update({_id: postId,
likes: {$not: {$elemMatch: {user: likeObj.user}}}},
{$addToSet: {"likes": likeObj}} ,function(err,doc){
});

Mongo db update to array object

I have array object inside my collection. i'm getting extra square bracket when i try to update data into the array object.
here is the code.
var comments = [{
'COMMENTED_BY' : employee.SYSTEM_USER_ID,
'COMMENT' : employee.FIRST_NAME+" "+employee.LAST_NAME+" Started working on this comlaint"
}];
if(req.body.complaint.comment){
comments.push({'COMMENTED_BY' : employee.SYSTEM_USER_ID,'COMMENT': req.body.complaint.comment});
}
Complaint.findByIdAndUpdate(
req.body.complaint.complaintId,
{$set: {'STATUS': 1}, $push: {"COMMENTS": comments}},
{safe: true, upsert: true},
function(err, model) {
My collection looks like below
{
"COMMENT" : "media delete confirmation UI issue",
"COMMENTED_BY" : ObjectId("575cc0b39dd420a41d202dad"),
"_id" : ObjectId("575fe9e1a5ee92201b58011e"),
"CREATED_AT" : ISODate("2016-06-14T11:26:25.003Z")
},
{
"COMMENT" : "Could someone explain to me how Luke Ronchi gets in when Tom Latham is a very capable keeper as well as batsman? Why not another specialist batsman/bowler?",
"COMMENTED_BY" : ObjectId("575cc0b39dd420a41d202dad"),
"_id" : ObjectId("575fea19a5ee92201b58011f"),
"CREATED_AT" : ISODate("2016-06-14T11:27:21.136Z")
},
[
{
"COMMENT" : "media delete confirmation UI issue",
"COMMENTED_BY" : ObjectId("575cc0b39dd420a41d202dad"),
"_id" : ObjectId("575fe9e1a5ee92201b58011e"),
"CREATED_AT" : ISODate("2016-06-14T11:26:25.003Z")
},
{
"COMMENT" : "Could someone explain to me how Luke Ronchi gets in when Tom Latham is a very capable keeper as well as batsman? Why not another specialist batsman/bowler?",
"COMMENTED_BY" : ObjectId("575cc0b39dd420a41d202dad"),
"_id" : ObjectId("575fea19a5ee92201b58011f"),
"CREATED_AT" : ISODate("2016-06-14T11:27:21.136Z")
}
]
i want to remove the extra [] brackets
This is happening because, you are just pushing array of objects, comment, into COMMENTS array field while updating. Use $each instead, while pushing array of objects.
See doc-$each for more info.
Try the following query. :-
Complaint.findByIdAndUpdate(
req.body.complaint.complaintId,
{$set: {'STATUS': 1}, $push: {"COMMENTS":{$each : comments}},
{safe: true, upsert: true})
Hope this will solve your issue.

How to get element from collection in Meteor if it multi-dimensional array or object or both?

I have collection "groups". like this:
{
"_id" : "e9sc7ogDp8pwY2uSX",
"groupName" : "one",
"creator" : "KPi9JwvEohKJsFyL4",
"eventDate" : "",
"isEvent" : true,
"eventStatus" : "Event announced",
"user" : [
{
"id" : "xfaAjgcSpSeGdmBuv",
"username" : "1#gmail.com",
"email" : "1#gmail.com",
"order" : [ ],
"price" : [ ],
"confirm" : false,
"complete" : false,
"emailText" : ""
},
...
],
...
"buyingStatus" : false,
"emailTextConfirmOrder" : " With love, your Pizzaday!! "
}
How can I get a value of specific element? For example i need to get value of "Groups.user.confirm" of specific group and specific user.
I tried to do so in methods.js
'pizzaDay.user.confirm': function(thisGroupeId, thisUser){
return Groups.find({ _id: thisGroupeId },{"user": ""},{"id": thisUser}).confirm
},
but it returns nothing.
Even in mongo console I can get just users array using
db.groups.findOne({ _id: "e9sc7ogDp8pwY2uSX"},{"user": ""})
The whole code is github
http://github.com/sysstas/pizzaday2
Try the following query:-
db.groups.aggregate(
[
{
$match:
{
_id: thisGroupeId,
"user.id": thisUser
}
},
{
$project:
{
groupName : 1,
//Add other fields of `user` level, if want to project those as well.
user:
{
"$setDifference":
[{
"$map":
{
"input": "$user",
"as": "o",
"in":
{
$eq : ["$$o.id" , thisUser] //Updated here
}
}
},[false]
]
}
}
}
]);
The above query will give the object(s) matching the query in $match inside user array. Now you can access any field you want of that particular object.
'pizzaDay.user.confirm': function(){
return Groups.findOne({ _id: thisGroupeId }).user.confirm;
I resolved it using this:
Template.Pizzaday.helpers({
confirm: function(){
let isConfirm = Groups.findOne(
{_id: Session.get("idgroupe")}).user.filter(
function(v){
return v.id === Meteor.userId();
})[0].confirm;
return isConfirm;
},
});
But I still think that there is some much elegant way to do that.

Categories