How can I use mongoose's "includes" - javascript

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.

Related

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

Set property value on mongoose result not working in Nodejs

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.

Breeze EntityQuery results do not honor projection with select

When executing a Breeze entityQuery using projection with a .select, the result set still returns every property instead of only those selected, even though the httpresponse only contains the properties in the select.
query = breeze.EntityQuery
.from('MyClass')
.select('name,code,id')
.skip(0)
.take(20);
return manager.executeQuery(query)
.then(function (resp) {
return resp.results;
})
.catch(function (error) {
return error;
});
the httpResponse contains instances with only name, code, and id.....However, the results contains every property for the entity with only those values populated as well as the entityAspect. I was under the impression that the a projection query would contain POJO objects rather than full Breeze entities:
http://www.breezejs.com/documentation/knockout-circular-references
"Construct a query using a select clause that names just the property values you'll display in your grid (plus the entity key so you can get the full entity later when you need to).
A projection query returns JavaScript objects with raw property values."
The issue in the above link is the reason that I am attempting this. I need to bind to a kendo grid (though using AngularJS bindings rather than Knockout).
Thanks!!

How to query documents in docpad based on arrays of objects

I have DocPad documents that look like this:
---
categories: [{slug: ""}, {slug: ""}, ...]
---
Document content.
How can I query all documents which have a predefined slug value in the meta.category array?
There's a few ways we can go about this.
Via a Template Helper and Query Engine's setFilter
https://gist.github.com/4556245
The most immediate way is via a getDocumentsWithCategory template helper that utilises Query Engine's setFilter call that allows us to specify a custom function (our filter) that will be executed against each model in the collection and based on it's boolean return value keep the model or remove it from the collection.
The downsides of this solution are:
We have to redefine our category information in each post
We have no immediate method of being able to get information about all the categories available to us
Via Template Helpers and the parseAfter event
https://gist.github.com/4555732
If we wanted to be able to get information on all the categories available to us, but still had the requirement of defining our categories every single time for each post, then we can use the parseAfter event to hook into the meta data for our documents, extract the categories out into a global categories object, and then update our document's categories with id references instead.
Downside is that we still have to have redundant category information.
Via Template Helpers and a global categories listing
https://gist.github.com/4555641
If we wanted to only define our category information once, and then just reference the categories ids within our posts, then this solution is most ideal.
I manage to create a "foo" collection for a given slug value "bar in docpad.coffee:
collections:
foo: (database) ->
database.findAllLive().setFilter("search", (model, value) ->
categories = model.get('categories')
return false unless Array.isArray categories
for category in categories
if (category.slug and category.slug == value)
return true
return false
).setSearchString("bar")
but when I try to create a helper function that returns a collection given the array meta ("categories"), the key ("slug") and value ("bar") of the object :
createCollection: (meta, key, value) ->
result = #getDatabase().createLiveChildCollection()
.setFilter("search2", (model, searchString) ->
objects = model.get(meta)
return false unless Array.isArray objects
for object in objects
if (object[key] and object[key] == searchString)
return true
return false
).setSearchString(value)
i get an empty collection when i try to call it.
I don't have a drop in solution, but have you seen the source code for the blog of docpad's author? There are some examples of querying for the existence of a metadata object attribute. Hope that helps!

Categories