How do you increment multiple fields in one query in mongoose? - node.js

How do you increment multiple fields in one query in mongoose?
For example, here is the working mongo query that I want to use with a mongoose model.
db.users.update({ userId:89 }, { $inc : { "subjectResults.attempts" : 1, "subjectResults.total_time" : 10, "subjectResults.total_score" : 100 } })
The above query is working in plain vanilla Mongo.
Edit: I have removed the confusing property name that lead to the comments below.

The APIs are nearly identical. Instead of db.users.update in straight mongodb, it's UserModel.update in mongoose. Pass in the exact same query and update options object.

Related

Maintain a custom order/sort of documents in MongoDB

In my web app XY I'm showing a classic list/table of data (documents) to the user. While all the sort functions provided by MongoDB ( and Mongoose, i'm using Mongoose) are pretty clear to me, I'm not interested in sorting by date or alphabetical order. In my case it would be important to let the user maintain a custom sort as in manually drag/drop items around to set a specific order of the documents (e.g. putting favourites in top of the list ). The UI to do this is a no-brainer but how to actually save the order in the database, brain-freeze.
Problem : How would I go about saving such a custom order of documents ?
What I use : NodeJS / Express / Mongoose (MongoDB)
Ideas
So far I could think of 2 ideas on how to do this.
A : Having an additional key (e.g. orderKey) in the mongoose Schema. Big con : I would need to keep constantly updating all documents orderKeys. Also I would need some sort of auto-increment for new documents.
const mySch = new Schema({
orderKey : { type : Number }
});
B : Creating one Schema/Model only for sorting, with an Array including all documents _ids for example. The order of the elements within the array would be used as reference for the custom order of the documents. Whenever the order changes, this Array would be changed as well.
conts orderSch = new Schema({
orderArray : { type : Array }
});
mongoose.model('Order', orderSch);
/* const customOrder = new Order({
orderArray : [ _id1, _id2, _id3, _id10, _id7, .. ]
}); */
Any more ideas or best practises are highly appreciated !

Query documents in an array in mongodb using node.js

How to query all documents present inside an Array which itself is present in a MongoDB collection under Node.js.
For example: I have a DB with a structure:
{
"name1":[{"height":"5.5"},
{"weight":"57"}],
"name2":[{"height":"6.1"},
{"weight":"74"}]
}
What query should I make to get all the documents( i.e. height, weight) of the array "name1"
Output should be :
{
{ "height":"5.5"}
{"weight":"57"}
}
My suggestion would be to reorganise the collection so each document has a key of name and key of physicalattributes e.g.
{
'name' : 'name1',
'physAttr': ['height': heightvalue,
'weight': weightvalue]
}
then suppose you wanted to find all documents with height 5.5, the query would be trivial
db.collection.find({ 'physAttr.height': 5.5 })
As described in the question each document in the collection has a different schema from the others (different name key for every document) making query operations difficult.

Update by Id not finding document

I am attempting to perform a relatively simple update using Mongoose:
var location = locationService.getLocation(typedLat, typedLong, travelRadius);
DocumentModel.update({_id : passedInId }, { location : location }, function(err, resp){
next(err, resp);
});
In this case passedInId is the string:
"561ee6bbe4b0f25b4aead5c8"
And in the object (test data I created) the id is:
"_id": ObjectId("561ee6bbe4b0f25b4aead5c8")
When I run the above however, matched documents is 0. I assume this is because passedInId is being treated like a string, however when I type it to an ObjectId:
var queryId = ObjectId(passedInId)
The result is the same, the document doesn't match. What am I missing? This seems like it should be obvious....
Mongoose will correctly interpret a string as an ObjectId. One of the following must be the case:
That record is not in the collection. Run a query in the mongo shell to check.
Mongoose I'd looking in collection other than the one containing your test data. Remember, by default, mongo will lowercase the name under which you register your model and will add an a "s" to it.
Lastly, and your answer speaks to this, maybe your model it's just not being updated with any new information.
This behavior was because I had not yet updated the model in mongoose to include the location element. There is no error, it just doesn't match or do anything.

Mongo DB Document only returns with "_id" that has "$oid"

I'm trying a very simple CRUD API with the MEAN stack. I entered several documents into a mongolab sandbox db. I could do a GET on all documents and they would all be returned. Then I tested GET by ID:
router.route('/api/v1/resources/:resource_id')
// get the resource with that id (accessed at GET http://localhost:8080/api/resources/:resource_id)
.get(function(req, res) {
Resource.findById(req.params.resource_id, function(err, resources) {
if (err)
res.send(err);
res.json(resources);
});
});
And it simply wouldn't work. I kept getting null. But the document existed. I could see it when I would do a GET on all documents.
Then I got another document to return, finally.
The difference? The record that returned had an id in this format:
{
"_id": { "$oid":"1234567890abc"}
}
But records that did not return had this:
{
"_id": "1234567890abc"
}
Can Anyone explain this to me? I entered the data with Postman and I didn't do anything different between the entries.
What is $oid?
What creates the $oid?
Why does that nesting matter for mongoose's findById()?
Thanks!
$oid is from Strict MongoDB Extended JSON.
All your queries to MongoDB database that contains _id conditions should wrap _id in ObjectId function like the following:
db.resources.findOne({_id: ObjectId("507c35dd8fada716c89d0013")};
MongoLab provides UI for querying to MongoDB via JSON syntax. But you can't use ObjectId in JSON due specification restrictions.
So, MongoLab uses Strict MongoDB Extended JSON for alias ObjectId() -> $oid.
{"_id": {"$oid":"507c35dd8fada716c89d0013"})
Same $oid you see in the output because MongoLab UI uses JSON also.
Mongoose automatically converts a string _id to MongoDB query so you don't need doing it manually. The following queries are equivalent:
Resource.findById("507c35dd8fada716c89d0013");
Resource.findById(new mongoose.Types.ObjectId("507c35dd8fada716c89d0013"));

Set field to empty for mongo object using mongoose

I have a document object that has an embedded sub-document.
To "clear" the sub-document, I try this:
obj.mysub = {};
obj.save();
This doesn't work, my object still has the contents of the mysub sub-document.
But this:
obj.mysub = undefined;
obj.save();
This does work, it removes my sub-document from the object.
My question is why doesn't the first version work? What is going on in Mongodb / Mongoose in the first example?
[edit] Why doesn't the empty object get saved in the first example above.
Mongoose sort of "protects" you from a lot of logic like you have presented in it's own internal resolution. So if you actually need to do this then do it at a lower level to the driver as in:
YourModel.update(
{ /*statement matching your document as a query */ },
{ "$unset": { "mysub": 1 } }
)
And per the normal MongoDB logic then this will work and remove that level in the document that was selected. See the $unset operator for more.

Resources