Set property value on mongoose result not working in Nodejs - javascript

Hullo,
I'm receiving a MongoDB object from a findById, and I'd like to convert the _id in that object from the ObjectID type to a string.
I'm doing something wrong, but I can't for the life of me figure out what it is!
I've created the following function:
student: async (parent, { _id }, context, info) => {
var student = await Student.findById(_id);
student._id = student._id.toString();
return student.toObject();
},
Using the debugger, I can see all the values are as expected, and student._id.toString() is correctly generating a string.
However, the value in the student object is not being set to the generated string.
I've tried adding an intermediate variable s to see if that makes a difference and it does not.
What could I be doing wrong here?
What should I do to further debug?
Thank you from a confused C++ developer!

Let me know if I'm far off here, but it looks like it's coming in as an object in the first place because of the curly braces surrounding _id.
If you remove that you might get what you need.
Other than that, you can try
student._id = JSON.stringify(student._id);
considering it should be coming back as JSON from your MongoDB

Why do you need to do _id.toString()? Mongoose document has id which is the string representation of the _id:
student: async (parent, { _id }, context, info) => {
var student = await Student.findById(_id);
return { id: student.id, ...student }
},
Also toObject accepts a transform function which as shown you can set on your schema so that you get the _id to behave like the id when toObject is called.
Also please note:
When you get a result from mongoose you get your data wrapped in a model object and your actual document is under the _doc property. So when you do your student._id = student._id.toString() you are decorating the model object and not the document. This is why the transform function makes more sense. Otherwise you have to decorate the _doc object which gets ugly really.

Related

How can I use mongoose's "includes"

I want to check my database which contains "likes" field as array type, so I come across this in mongoose documentation but I don't actually know how to use it :
https://mongoosejs.com/docs/api/array.html#mongoosearray_MongooseArray-includes
Here is what I just tried
Products.find({_id:uniqueId}, {$includes:{likes:req.user._id}}, function(err, result){......})
To your image:
It is complaining because you used Products.find. As you are passing in two objects, it expects the second object to be a projection. Projection selects fields from the returned documents to only get only the fields that you need.
Try to get the product with the uniqueId (which I hope is the productId...).
Product.findById(productId, function (err, result) { // callback })
Inside the callback you can check if your userId is included in the likes array.

How can I use variables in an update operation in mongodb that involves an array or another type of embedded or nested document?

The document in the target collection ("myCollection") has a field called "japanese2". This is an array (or an object) that contains an object that contains a property called "japanese2a". The value of this property is initially set to 0 (although it may change later). I want to change this value to 100 with a script in node.js (I am using the Express framework). The database is Mongodb, the free cloud version called Atlas.
If I do this without using variables, it works well:
db
.collection("myCollection")
.updateOne({username:username}, {"$set":{"japanese2.0.japanese2a":100}});
However, if I try this using variables for both the field name, "japanese2", and the name of the element/property in the array/object, "japanese2a", it fails. I have tried the below and other variations but I couldn't find a solution. I have researched stackoverflow for an answer but couldn't find a solution.
There is only one element/property in the array/object to start with.
var field = req.body.fieldName; //want to set this for the field name="japanese2"
var task = req.body.question; //want to set this for the name of the element="japanese2a"
var myField = [task];
field = myField;
var fieldPos = field[0];
.
.
.
db
.collection("myCollection")
.updateOne({username:username}, {"$set":{[fieldPos]:100}});
The above creates a new field called "japanese2a":100" but it does not appear in the array under the field called "japanese2", which is what I want.
I don't get any error messages when I do the above in the console (probably mostly due to the fact that I haven't put in error statements/functions to catch errors), but the output is not correct.
Another way of updating that I found from here:
https://www.codementor.io/#prasadsaya/working-with-arrays-in-mongodb-16s303gkd3
that involves using something like this:
db.posts.updateOne(
{ _id : ObjectId("5ec55af811ac5e2e2aafb2b9"), "comments.user": "Database Rebel" },
{ $set: { "comments.$.text": NEW_CONTENT } }
)
doesn't work for me, as I don't know if the initial value of the element in the array will always be a zero or some other constant. And there is only one element in the array initially. I can only use the username for the match part in the updating. I can't make an expression that is a perfect match for some element in the array.
The update solution from here: MongoDB update data in nested field
db.users.update ({_id: '123'}, { '$set': {"friends.0.emails.0.email" : '2222'} });
works, and that is what I used successfully to update in the first updating attempt above, but I don't know how to incorporate variables into the updating operation, specifically a variable for the field name ("japanese2") that holds the array or the object, and the name of the first and only element/property in the array/object ("japanese2a").
EDITED: I asked for a solution for an "array" originally, but either a field that acts an array (that holds elements that act as objects) or an object (that holds other objects as properties) works in my case, so I edited the question body and title. Also, the accepted solution works with the field as an entity that holds an array, or as an entity that contains an object inside it.
In either case, if there is already a field with the appropriate name, an object is created (if it didn't already exist) as an object of that object called "field" or the array called "field", and the object's property is set as according to the variables in the script.
If the field doesn't exist, it's created (as an object), and this object contains another object that contains the property ("task" as the name and "100" as the value for the name-value pair). So the newly created "field" object contains an object as its property. The property of this object is a name-value pair of "japanese2a" and "100".
If the script is run again, with a different "task" name (eg. "japanese2b"), another property is created, with the name of "japanese2b" and the value of "100". It is created within that same object that is "inside" the "field" object, so the object field.0 (the object within the "field" object) ends up looking like this: {japanese2a: 100, japanese2b: 100}. And the object called "field" looks like this: {{japanese2a: 100, japanese2b: 100}}.
I think something like
var field = req.body.fieldName // japanese2
var task = req.body.question; // japanese2a
var updateObj = { $set : {} };
updateObj.$set[field + '.0.' + task] = 100
db
.collection("myCollection")
.updateOne({username:username}, updateObj);
Might work

retrieve key names from firebase react-native

I have a little problem regarding Firebase and retrieving names of parent keys. Like in this example I want to get the names of the keys, not their values:
Pls have a look in my db how it looks now, its exactly the same like in the JS sandbox:
When I try to implement this in my react-native project, basicly with plain JS in this part, it looks like this:
const sendletter = () => {
console.log("letter send");
firebase.database().
refFromURL("https://SOMEDATABASE.firebaseio.com/numers").
once("value").then(snapshot => {
for(key in snapshot){
console.log(key)
}
})
};
The problem I just face now it the outcome of the console in my IDE:
null letter send node_ ref_ index_ val exportVal toJSON exists child
hasChild getPriority forEach hasChildren key numChildren getRef ref
I tried to provide you as many pictures so the problem gets really clear and also my goal I want to archieve, to get the key names itself, NOT the values the keys are linked to. Any help would be appriciated!
You want to use snapshot.val() instead of just the DataSnapshot object
for(key in snapshot.val()){
console.log(key);
}
When you are looping through just the snapshot variable, you are looking at all the keys in that DataSnapshot that is returned from firebase and not your actual data. If you check out Firebase docs, you'll see what the DataSnapshot object represents and how to actually get your data from the database FROM their DataSnapshot object that is returned: https://firebase.google.com/docs/reference/node/firebase.database.DataSnapshot
If you look close enough you can see that all the methods and values that this DataSnapshot object contains is actually what was being printed in your console all along

Why there is two property named _id and id and only one is visible in object return by mongoose?

When I print the object returned after querying in MongoDB using mongoose I get an object containing one of the keys as '_id'. But when I try to print the object's property id and _id by accessing the object then It doesn't say undefined for the id instead It prints the same id as _id. I am attaching the screenshots for the code and output below.
Here is the code snippet
const user = await User.findById(req.params.id);
console.log(user);
console.log(user.id, user._id);
In the following output, we can see that id and _id contains the same value even though there is no property as 'id' available in user object
{
role: 'user',
_id: 5fc6cad25884d51790aad697,
name: 'Test 001',
email: 'test001#gmail.com',
__v: 0
}
5fc6cad25884d51790aad697 5fc6cad25884d51790aad697
I suppose the main confusing part for you is id where it comes from. Here is explanation from the documentation:
Mongoose assigns each of your schemas an id virtual getter by default
which returns the document's _id field cast to a string, or in the
case of ObjectIds, its hexString. If you don't want an id getter added
to your schema, you may disable it by passing this option at schema
construction time.
const schema = new Schema({ name: String }, { id: false });
Virtuals are document properties that you can get and set but that do not get
persisted to MongoDB. The getters are useful for formatting or
combining fields, while setters are useful for de-composing a single
value into multiple values for storage.
you can read more about it in documentation:
id - https://mongoosejs.com/docs/guide.html#id
virtuals - https://mongoosejs.com/docs/guide.html#virtuals
Check that the user object having some instance related issue or not , otherwise it won't happen.

Get value of object inside of array which is inside an object itself

I have a quick question which I seem to be tripped up on.
I have a data structure like so:
data: {
accounts: [{
info: false
}]
}
Is there a "fancy" React way for me to get the value of the boolean associated with the info key?
I can of course retrieve the value with using map or find, but it always ends up being somewhat convoluted or involved code.
If I do something like
const { accounts } = data;
const customer = accounts.map(a => a.info);
The value for customer always ends up coming back as [false] instead of just false, which is really confusing me, because I am not sure why it would come back inside of an array, where it is not an array to begin with, and it is being mapped out of an array (accounts).
I had the same result when using forEach and find.
Is there something I'm missing? There has to be a quick Reactive one-liner to get the boolean value I'm looking for, and set it to a variable.
Anyone...?
data.accounts[0].info
or
Using underscore.js
_.first(data.accounts).info

Categories