Mongoclient: how to set a value of an embedded document - node.js

Im using the MongoClient in nodejs. I want to update an specific embedded document value, but I don't know how to do that.
In the mongo shell it works like a charm With {$set{doc.doc : "test"}}
But when I'm trying to use it in exactly the same way in node, It gives me the error that the dot isn't undestandable.
I've tried it as a string, which doesn't work either.
Does somebody got a solution for this problem?
EDIT:
Json doc in the Mongodb:
{
name : test,
doc : {},
}
and I want to add the following key-value pair to the 'doc'-document
test:test
Relevant Code part (How i thought It should work)
db.collection("test").update({name:test},{$set:{doc.test:test}}, callback)

You can try setting up the update object in a variable using the array-syntax style, e.g:
var update = { $set: {} };
update["$set"]["doc"]["test"] = "test"; // -> same as update = {"$set": {"doc": {"test": "test" } } }
var query = {"name": "test"};
db.collection("test").update(query, update, callback);

Related

Mongoose: How to update nested fields with fields present in request body only?

Looking to update lookupSchema images nested fields
var lookupSchema = new Schema({
images:{
"img1":String,
"img2":String,
"img3":String,
"img4":String
}
}
As I don't know which fields are available in request body during findOneAndUpdate operation, I am unable to assign like this
$set: {
'images.img1': req.body.img1,
'images.img2': req.body.img2,
'images.img3': req.body.img3
}
If I code like above and specify all fields, already available fields become empty after update due to unavailable fields in request.
Need something like this to update available fields
$set: { "images.$[element]" : req.body }
I have searched a lot but unable to find a solution.
You can simply create a function like below to be able to achieve your result.
function update() {
let temp = {};
for(let field in req.body) {
temp["images."+field] = req.body[field];
}
db.collection.findOneAndUpdate({._id:...},{$set:temp},{upsert:true},function(err,result)
{...});
}

findOneAndUpdate works part of the time. MEAN stack

I'm working with the mean stack I'm trying to update the following object:
{
_id : "the id",
fields to be updated....
}
This is the function that does the updating:
function updateById(_id, update, opts){
var deferred = Q.defer();
var validId = new RegExp("^[0-9a-fA-F]{24}$");
if(!validId.test(_id)){
deferred.reject({error: 'invalid id'});
} else {
collection.findOneAndUpdate({"_id": new ObjectID(_id)}, update, opts)
.then(function(result){
deferred.resolve(result);
},
function(err){
deferred.reject(err);
});
}
return deferred.promise;
}
This works with some of my objects, but doesn't work with others.
This is what is returned when it fails to update:
{
ok: 1,
value:null
}
When the function is successful in updating the object it returns this:
{
lastErrorObject: {}
ok: 1
value: {}
}
It seems like Mongo is unable to find the objects I'm trying to update when it fails. However, I can locate those objects within the Mongo shell using their _id.
Does anybody know why the driver would be behaving this way? Could my data have become corrupt?
Cheers!
I found the answer and now this question seems more ambiguous so I apologize if it was confusing.
The reason I was able to find some of the documents using ObjectID(_id) was because I had manually generated some _id fields using strings.
Now I feel like an idiot but, instead of deleting this question I decided to post the answer just in case someone is running into a similar issue. If you save an _id as a string querying the collection with the _id field changes.
querying collection with MongoDB generated _ids:
collection.findOneAndUpdate({"_id": new ObjectID(_id)}, update, opts)
querying collection with manually generated _ids:
collection.findOneAndUpdate({"_id": _id}, update, opts)
In the second example _id is a string.
Hope this helps someone!

Finding a document, converting it into an object, and identifying it with a variable in Mongoose

Background: I have a mongo database named test with a collection called collection. There is a single document in test.collection:
{ "_id" : ObjectId("64e4a6f9d1d7ba45250dc2c1"), "key" : "value"}
Question: Using Mongoose, what is a way to grab the lone document found in test.collection, convert it into a javascript object, and to identify it with the variable object? For example, we should have that
console.log(object.key)
returns "value".
EDIT : I have tried the following, which didn't work:
var Schema = mongoose.Schema;
var Model = db.model('Model', mongoose.Schema({}),'collection');
var doc = Model.findOne();
console.log(doc.key); // doesn't show "value" as expected
Do it this way (as stated on my comment):
Model.find(function (err, docs) {
if (err) return console.error(err);
console.log(docs[0].key);
});
I also recommend taking another look to the docs, it's always good to refresh the basic concepts.

How do I get this nested schema working in Mongoose?

So I'm trying to figure out how to how to save multiple commands in a command list but everything I've tried hasn't worked. This is how I have it set up so far but when it saves, it saves in the format of
"command_list" : [ { "action" : "goto,goto", "target" : "http://www.google.com,http://www.cnn.com" } ]
when I really want something like
"command_list" : [ "command" : { "action" : "goto", "target" : "http://www.google.com" },
"command" : { "action" : "goto", "target" : "http://www.cnn.com" } ]
where there are multiple commands. So far my app.js is storing the data like this
var configSample = new Configurations({
command_list_size: request.body.command_list_size,
command_list: [ {action: request.body.action, target: request.body.target}]
});
and the model looks like this
var mongoose = require("mongoose");
var command = mongoose.Schema({
action: String,
target: String
});
var configSchema = mongoose.Schema({
command_list_size: Number,
command_list: [command]
});
module.exports = mongoose.model('Configurations', configSchema);
So how do I get that nesting action going? Thanks!
It looks like you're not packing the data right when you send it to the server. If you use the following:
command_list: [ {action: request.body.action, target: request.body.target}]
it's going to grab all of the actions and lump them together and do the same with the targets. You'd be better off sending an array to your server with the documents already nested in them.
The other option would be to parse the data to pull out the elements once you receive it on your server, but I think it'd be easier to just package it right in the first place.
ADDITION:
If you wanted to split what you have, you could use the String.split() method and rebuild the object:
// not certain the chaining will work like this, but you get the idea. It works
// on the string values you'll receive
var actions = response.body.action.split(',');
var targets = response.body.target.split(',');
// the Underscore library provides some good tools to manipulate what we have
// combined the actions and targets arrays
var combinedData = _.zip(actions, targets);
// go through the combinedData array and create an object with the correct keys
var commandList = _.map(combinedData, function(value) {
return _.object(["action", "target"], value)
});
There may be a better way to create the new object, but this does the trick.
EDIT:
I created a question about trying to refactor the above code here.

Increasing one field in a MongoDB collection with Mongoose

I'm trying to increment a value in a collection in my MongoDB database through Mongoose. This is the demo code shown on the Mongoose website:
var conditions = { name: 'borne' }
, update = { $inc: { visits: 1 }}
, options = { multi: true };
Model.update(conditions, update, options, callback)
And I have something like this:
var conditions = { "uniqueId" : itemId };
var update;
if(increase)
update = {$inc : {inStock : 1}};
else
update = {$dec : {inStock : 1}};
Item.update(conditions, update, {}, callback);
As you can see there is not much difference from the Mongoose's website code.
The problem is that when this piece of code is executed, I end up having in my collection one field called $dec (or $inc) which has an object as a field in the form {inStock : 1}. I just would like to increment the inStock entry of the collection. In the Schema I have:
var ItemToSell = new Schema({
uniqueId : { type: Number, index: true }
, name : String
, type : String
, inStock : Number
});
Can anyone point out what am I doing wrong?
Thanks a lot.
A) Make sure you're Mongoose is up-to-date. Older versions were very buggy on Model.update operations because Mongoose attempts to infer when you are merely passing a new object, in which case it turns your update object into a $set operation.
B) Try removing the empty {} from your function call. It is optional, and by passing an empty object rather than actual options, you may be confusing Mongoose into setting the { safe: false } option, which could also be causing your problem. I have not checked the source code to confirm that that could be the issue, but it's probably worth a try.

Resources