I have a db structure like this:
{ "_id" : ObjectId("5fd48e12e5e0fd174c1a7260"),
"races" : {
"example1" : { "date" : "12/18/2020", "status" : "pending" },
"example2" : { "date" : "12/18/2020", "status" : "domestic" }
}
and I am attempting to just remove example 1 by using the following block of code(javascript):
self.db = client.db("authinfo");
self.collection = self.db.collection("users");
this.delete_both_races = function (user1) {
self.collection.updateOne({user:user1} ,{$unset:{races:"example1"}} ,function(error,result){});
same thing happens when running the following command in the mongo.exe command line program:
db.users.updateOne({user:"anything"} , {$unset:{races:"example1"}})
I get the result of(remaining elements after unsetting) :
{ "_id" : ObjectId("5fd48e12e5e0fd174c1a7260") }
desired result :
{ "_id" : ObjectId("5fd48e12e5e0fd174c1a7260"),
"races" : {
"example2" : { "date" : "12/18/2020", "status" : "domestic" }
}
You should unset races.example1 instead of races.
From MongoDB document,
The specified value in the $unset expression (i.e. "") does not impact the operation.
To specify a in an embedded document or in an array, use dot notation.
Mongo Playground
Related
I am trying to change an element object that is within an array in a document on Robo3T.
The structure looks like this:
{
"_id" : ObjectId("1234"),
"source" : "BW",
"sourceTableName" : "lwtrmls",
"tableName" : "tier",
"type" : "main",
"primaryKeys" : [
{
"sourceField" : "tier_id", // <~~~~ This is what I am trying to update!
"reportingField" : "bw_id",
"type" : "integer"
}
]
}
Basically trying to change tier_id under primaryKeys and sourceField to trmls_id.
I have tried something like db.my_collection.update( {_id : "1234"}, {$set : {"primaryKeys.0.tier_id" : "trmls_id"}} ) and that does not seem to be working. Is there a clean way to do this?
Basically you need to use $(update)
In you case you need to execute current query:
db.my_collection.update( {_id : "1234", "primaryKeys.sourceField":"tier_id"}, {$set : {"primaryKeys.$.sourceField" : "trmls_id"}} )
Updated:
If you want to update not only first element in array for current filters, but all, you could use $[]
db.my_collection.update( {_id : "1234", "primaryKeys.sourceField":"tier_id"}, {$set : {"primaryKeys.$[].sourceField" : "trmls_id"}, { multi: true }} )
My Firebase structure is below
{
"Test1 Lab" : {
"Equipment" : "3-D printer",
"Hours" : "7AM-6PM",
"Location" : "Library",
"Name" : "Digital Lab"
},
"Test2 Lab" : {
"Equipment" : "Oculus",
"Hours" : "7AM-6PM",
"Location" : "Hall",
"Name" : "Test Lab"
}
}
The top level is called "makerspace". I am trying to get the Name, Equipment, and Hours of the item where the Location is "Library" I ran the code:
var red = database.ref('makerspace');
return red.orderByChild('Location').equalTo("Library").once('value').then(function(snapshot){
console.log(snapshot.child("makerspace").child("Name").key);
});
And I get "Name". However, when I change .key to .val(), I should expect to get "Digital Lab", but I get null. I don't know how to fix this.
The snapshot is already on the makerspace node, so it should be:
var red = database.ref('makerspace');
return red.orderByChild('Location').equalTo("Library").once('value').then(function(snapshot){
console.log(snapshot.child("Name").val());
});
Try this
var red = database.ref('makerspace');
return red.orderByChild('Location').equalTo("Library").once('value').then(function(snapshot){
snapshot.forEach(function(data) {
console.log(data.val());
});
});
I would recommend to access snapshot data like this,
red.orderByChild('Location').equalTo("Library").once('value').then(function(snapshot){
console.log(snapshot.val()); <==========
// result would be
{ "Test1 Lab" : { "Equipment" : "3-D printer","Hours" : "7AM-6PM","Location" : "Library","Name" : "Digital Lab" } }
}
To get properties you can do,
snapshot.val()['Test1 Lab']['Name'] or snapshot.val()['Test1 Lab'].Name
snapshot.val()['Test1 Lab']['Hours']
Now you can get 'Test1 Lab' using Object.keys(snapshot.val())[0]
snapshot.val() is like JSON Object, so just access its properties like you did for objects. No need to use child() method to access data.
There is such a document structure in MongoDB
{
"_id" : ObjectId("58f7d556aa52ce456672a67e"),
"created" : ISODate("2017-04-19T21:23:34.315Z"),
"context_task" : [
{
"task" : "some text ",
"status" : false,
"_id" : ObjectId("58f7d559aa52ce456672a67f")
}
],
"head" : {
"userID" : "58f48037fc894e19a3f7b81b",
"head_task" : "test record "
},
"__v" : 0
}
I add data to the context_task.task using the following query:
task.findOneAndUpdate({"_id": req.body.id_project},
{$push: {'context_task': {'task': req.body.input_task,'status': false}}},{new: true},
function (err, doc) {
if (err) return next(err);
var body = req.body.id_project+","+req.body.input_task;
console.log(doc);
res.status(200).send(body);
});
Tell me, how can I get the context_task._id of a new record after inserting it? In this case, the entire document is returned.
Every mongo document is associated with a default _id, in case not provided it will be ObjectId.
In case you want to use _id value for any other purpose, why don't you have your own _id value, which has to be unique throughout collection. The value can be of any datatype as well as nested also.
Here is my JSON and Code which gives only array but not it values. As I had used push it generating Unique Id from, which I am not getting. All the values that stored in that id.
{
"nitin" : [ {
"mobile" : {
"-K7GalDi5aAahDENCRi" : {
"name" : "file:///D:/Software%20Drive/addItem.html?category=mobile",
"price" : 345,
"quantity" : 34
}
},
"perfume" : {
"-K7K7HSu4rQNwbH3ud0H" : {
"name" : file:///D:/Software%20Drive/addItem.html?category=perfume",
"price" : 1000,
"quantity" : 20
}
}
}]
}
This is my code
fbref.on("value", function(snapshot) {
var newPost = snapshot.val();
console.log(newPost);
fbref.on("child_added", function(newPost,pre){
newchild=newPost.val();
console.log(newchild);
var n=newPost.key();
console.log("this is key"+n);
console.log("Name"+newchild.name);
console.log("Price"+newchild.price);
console.log("Quantity"+newchild.quantity);
});
});
The child_added event will fire when a child node is added directly under the location that you're querying.
So if you're querying the root of the JSON you show, a child_added will fire for nitin. And then if we'd add puf, a child_added will fire for that too.
{
"nitin" : [ {
...
}],
"puf": [ {
...
}],
}
If you want to receive a child_added for items inside mobile or perfume, you will need to attach a child_added on the parent node of those:
fbref.child('nitin').child(0).child('mobile').on('child_added'...
Or:
fbref.child('nitin/0/mobile').on('child_added'...
See this jsbin for a working sample of this.
I have a doc with an array of embedded docs ("comments"), and an example that looks like this:
{
"_id" : ObjectId("539e9213209e743d107e7202"),
"article" : "article1",
"comments" : [
{
"comment" : "comment1",
"created" : ISODate("2014-06-16T06:43:38Z"),
"_id" : ObjectId("539e921a209e743d107e7203"),
"read" : {
"marked" : false
},
"timesent" : {
"datetime" : "Mon Jun 16 2014 02:43:38 GMT-0400 (EDT)",
"hour" : 2,
"minute" : "43",
"second" : 38,
"am" : true,
"month" : 5,
"day" : 16,
"year" : 2014
}
}
]
}
For each comment in the comments array, is there a way to batch update the field "read" : {"marked" : true}?
Am working with node.js, and have something like this in mind (the questionable portion begins with
if (req.body.readComment) {..
// update the article with this id (accessed by PUT at
// http://localhost:4200/api/v1/articles/:article_id)
.put(function(req, res) {
Article.findById(req.params.article_id, function(err, article) {
if (err)
res.send(err);
if (req.body.comment) {
article.comments.push({
comment : req.body.comment,
timesent :
{
datetime : req.body.datetimeNow,
hour : req.body.hourNow,
minute : req.body.minuteNow,
second : req.body.secondNow,
am : req.body.amNow,
month : req.body.monthNow,
day : req.body.dayNow,
year : req.body.yearNow
},
read :
{
marked : req.body.readComment,
datetime : req.body.readCommentDatetime
},
created : req.body.datetimeNow
});
} // if newComment
if (req.body.readComment) {
var comments = // some sort of .find ?
var embeddedDoc;
for (var i=0, length=comments.length; i < length; i++){
embeddedDoc = comments[i];
embeddedDoc_id = // something to find the embedded doc_id ?
console.log(i);
article.comments.push({ // maybe push to the embedded doc_id
read :
{
marked : req.body.readComment,
datetime : req.body.readCommentDatetime
}
});
};
} // if readComment == true (from ajax .put)
// save the article, and check for errors
article.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Update "' + req.params.article_id });
});
});
})
Well as each comment would need to be identified within the array, the term "Bulk" doesn't really apply as they would be inherently separate. As for being able to just say "Update all of these 'comments' and mark them as true", that is not directly supported.
But on the other hand you can streamline this with Bulk update operations. So for a "list" of "comment" _id values you could do this:
var bulk = collection.initializeOrderedBulkOp();
comments.forEach(function(commentId) {
bulk.find({ "comments._id": commentId }).updateOne({
"$set": { "comments.$.read.marked": false }
});
counter++;
if ( counter % 500 == 0 ) {
bulk.execute(function(err,result) {
// do something with the result
bulk = collection.initializeOrderedBulkOp();
counter = 0;
});
}
});
// Catch any under or over the 500's
if ( counter > 0 )
bulk.execute(function(err,result) {
// do something with the result here
});
That at least avoids you sending an update "over the wire" to the server instance for every single "comment" _id you send into the API. By batching the results this results in less traffic and less time waiting for the response in the callback.
You can likely better this example with "async" so even looping the input list is a non-blocking operation. The batch sizes can vary, but this is just a safe example to stay under the 16MB BSON hard limit, as the whole "request" is equal to one BSON document.