How to find and update a mongoose model? - mongodb

I have a model userDatas and it contain a list of user data.
[{
"_id" : ObjectId("5bb6730721f28a295436b36f"),
"userId" : "5bb6730721f28a295436b36e",
"reputationNumber" : 0,
"questions" : [],
"answers" : []
},
{
"_id" : ObjectId("5bb6738c21f28a295436b371"),
"userId" : "5bb6738c21f28a295436b370",
"reputationNumber" : 0,
"questions" : [],
"answers" : []
}]
I want to filter by userId and add "5bb7d72af050ca0910282ff4" string to questions array. How to accomplish that?
//Userdatas.find

Since you are using mongoose you can use the findOneAndUpdate and addToSet to achieve this:
Userdatas.findOneAndUpdate(
{userId: "5bb7d72af050ca0910282ff4"},
{$addToSet: {questions: '5bb7d72af050ca0910282ff4'}},
function (err, result) {
...
}
)

The query would look something like
Userdatas.findOne({where: {userId: "5bb7d72af050ca0910282ff4"}}, function (err, data) {
if (!err && data) {
var questionsArr = [];
if (data.questions) {
questionsArr = data.questions;
}
questionsArr.push('5bb7d72af050ca0910282ff4');
data.updateAttributes({questions: questionsArr}, function(err, updateData) {
cb (err, updateData);
});
} else {
cb (err, {});
}
});
Unfortunately you would need 2 queries to do this. First, to get the document where the userId matches your required userId and to push the string to the questions array and update the document.
EDIT:
The first findOne query fetches the document where userId matches our user. The updateAttributes query is executed on the document that was fetched, so it updates the correct document.

Related

MongoDB - change values from one ENUM type to another

I have MongoDB entries which looks like this:
{
"_id" : ObjectId("57288862e4b05f37bc6ab91b"),
"_class" : "mydomain.ScheduleAbsenceContainer",
"containerStart" : ISODate("2016-04-06T07:30:00Z"),
"containerEnd" : ISODate("2016-04-06T10:00:00Z"),
"scheduleIntervalContainerAbsenceType" : "SCHOOL",
"scheduleIntervalContainers" : [
{
"_id" : null,
"marker" : 6,
"containerType" : "SCHOOL",
}
]
}
and I will change all scheduleIntervalContainerAbsenceType from SCHOOL to SPARE_TIME and also all containerType's from SCHOOL to SPARE_TIME.
Is there a simple possibility to do this?
Below code does what you want. It updates all the documents which has the "SCHOOL" value for "scheduleIntervalContainerAbsenceType" keys.
db.collection_name.find({"scheduleIntervalContainerAbsenceType" : "SCHOOL"})
.forEach(function (doc) {
doc.scheduleIntervalContainers.forEach(function (sch) {
if (sch.containerType === "SCHOOL") {
sch.containerType="SPARE_TIME";
}
});
doc.scheduleIntervalContainerAbsenceType="SPARE_TIME";
db.collection_name.save(doc);
});
If you want to update all the documents without checking "scheduleIntervalContainerAbsenceType" value (still updating it to "SPARE_TIME") change your query like that.
db.collection_name.find({})
.forEach(function (doc) {
doc.scheduleIntervalContainers.forEach(function (sch) {
if (sch.containerType === "SCHOOL") {
sch.containerType="SPARE_TIME";
}
});
doc.scheduleIntervalContainerAbsenceType="SPARE_TIME";
db.collection_name.save(doc);
});

Why does my list of items sort incorrectly after many multiple updates?

I'm using Meteor, and I have a list of items like:
Todo A
Todo B
Todo C
Todo D
But then after calling multiple updates one after another:
Todos.find().forEach(function(todo) {
Todos.update(todo._id, {$set: {
strength:s,
retention:r,
}},
function(err, res){
if(err){throw err}
console.log('updated '+res+' doc');
})
})
Todo A
Todo D
Todo C
Todo B
the list order becomes messed up. If I refresh it's fine again and sorted accordingly. Why could this be?
Template.listsShow.helpers({
editing: function() {
return Session.get(EDITING_KEY);
},
todosReady: function() {
return Router.current().todosHandle.ready();
},
todos: function(listId) {
var obj = Todos.find({listId: listId}, {sort: {createdAt : 1}});
return obj;
}
});
//Server Side
Meteor.publish('todos', function(listId) {
check(listId, String);
return Todos.find({listId: listId});
});
{
"_id" : "6pELT5pmGoXQhh2eG",
"createdAt" : ISODate("2016-01-02T23:58:12.236Z")
}
{
"_id" : "4ES3hbJX76nLCJGGL",
"createdAt" : ISODate("2016-01-02T23:58:12.236Z")
}
{
"_id" : "NzModCoCHcbWdWo22",
"createdAt" : ISODate("2016-01-02T23:58:12.236Z")
}
{
"_id" : "tzgK3EdMrBi8SbGBn",
"createdAt" : ISODate("2016-01-02T23:58:12.236Z")
Based on our conversation above, it looks like the issue had to do with the fact that several of the documents had the same value for createdAt. Therefore sorting on that field alone would result in an arbitrary ordering. If the documents were generated from a script, you could try randomizing the date. Additionally, you could sort on more than one field, for example: {sort: {createdAt: 1, message: 1}}.

How do i get all keys in Mongodb collection?

I saw few solutions but those are not exact my solution. I have a DB with name results and collection name is marks like below:
db.marks.find();
{ "_id" : ObjectId("54f57522627af4bfdcf79764"), "name" : "John", "scroe1" : 23, "score2" : 21, "score5" : 12 }
{ "_id" : ObjectId("54f5761a627af4bfdcf79765"), "name" : "Mike", "scroe2" : 22, "score3" : 20, "score4" : 22 }
{ "_id" : ObjectId("559d0bc521cb2e056507c3e3"), "name" : "Bush", "score2" : 30 }
I tried with
var doc=db.marks.findOne(); for (var key in doc) print(key);
and i got
_id
name
score1
score2
score5
But i Want all keys in collection like below:
_id, name, score1, score2, score3, score4, score5
name
scroe1
score2
score3here
findOne will only return the first found document. Since the first document you list does not have the score3 and score4 keys, it will not display them. If you want to show all root-level keys across all documents, you would need to iterate through all the documents in the db.
var keys = [];
db.marks.find().forEach(function(doc){
for (var key in doc){
if(keys.indexOf(key) < 0){
keys.push(key);
}
}
});
print(keys);
mr = db.runCommand({
"mapreduce" : "my_collection",
"map" : function() {
for (var key in this) { emit(key, null); }
},
"reduce" : function(key, stuff) { return null; },
"out": "my_collection" + "_keys"
})
Then run distinct on the resulting collection so as to find all the keys:
db[mr.result].distinct("_id")
["foo", "bar", "baz", "_id", ...]
Mongodb find() command has two arguments first one is query and second is projections.
Something like db.collection.find(query,projection).
if the document is db.myCol.find();, then it returns:
{
{
_id:1
name: ''hello',
age: 23
}, {
_id:2
name: ''bollo',
age: 27
}
}
And db.myCol.find({},{_id:1}); returns:
1
2

MongoDB - Aggregate $match on ObjectId

I have a schema that looks like this:
var mongoose = require('mongoose');
module.exports = mongoose.model('Owner',{
username: String,
blocks: {type:mongoose.Schema.Types.ObjectId, ref: 'Block'},
});
I'm trying to run a query to see if Owner has a reference to Block's id. Owner has an array of ObjectIds. When I run db.owners.aggregate({$match: {username: 'example'}},{$unwind: "$blocks"},{$project: { _id : 1,blocks: 1}}) it returns:
{ "_id" : ObjectId("550d9dc64d9dc3d026fadfc7"), "blocks" : ObjectId("550dc117dc9605ab27070af7") }
{ "_id" : ObjectId("550d9dc64d9dc3d026fadfc7"), "blocks" : ObjectId("550dc123dc9605ab27070af8") }
{ "_id" : ObjectId("550d9dc64d9dc3d026fadfc7"), "blocks" : ObjectId("550dc12edc9605ab27070af9") }
{ "_id" : ObjectId("550d9dc64d9dc3d026fadfc7"), "blocks" : ObjectId("550dc157dc9605ab27070afa") }
How can I match the block id? I've tried db.publishers.aggregate({$match: {username: 'example'}},{$unwind: "$blocks"},{$project: { _id : 1,blocks: 1}},{$match : {"blocks._id" : '550dc157dc9605ab27070afa'}}) but that doesn't work.
I think you don't need aggreation for that, you can use a simple find() or findOne() query:
var Mongoose = require('mongoose');
var ObjectId = Mongoose.Types.ObjectId;
Owner.findOne({ username: 'example', blocks: new ObjectId('550dc157dc9605ab27070afa') }, function (err, owner) {
...
});
that does not work right now with versions > 3.8.31
i've wasted countless hours on that one, should have tested the earlier mayor sooner...

Retrieve only the queried element in an object array

I have a collection with organizations. Each organization has members. I want to run query to check if a user is a member of that organization.
I tried this:
mongoose.model('organization').find({orgId: paramOrgId}, function(err, organization){
organization.find({'members.user':req.user._id}, function(err, user){
if(!user) res.send(401) //The user is not a member in organization
if(user) res.send(200);
});
}
return res.send(401);
});
Apparently you don't have 'find' on callback. How should I do this instead?
Example of organization doc:
> db.organizations.find().forEach(printjson);
{
"_id" : ObjectId("5381d5d11409f125475fcc90"),
"orgId" : 5,
"title" : "ExampleCorp",
"members" : [
{
"tier" : 1,
"user" : ObjectId("5381d5d11409f125475fcc8c")
},
{
"tier" : 2,
"user" : ObjectId("5381d5d11409f125475fcc8d")
},
{
"tier" : 3,
"user" : ObjectId("5381d5d11409f125475fcc8e")
}
]
}
Here it is in one query if you just want to check if a user is a member of an organization.
// Use findOne so that it returns one document instead of a collection
mongoose.model('organization').findOne({
// Instead of querying twice, just set both conditions
'orgId': paramOrgId,
'members.user':req.user._id
},
'_id', // We'll just select the _id field. We don't need the whole organization document
function (err, org) {
if (err)
return res.send(500); // Error!
if (org)
return res.send(200);
else
return res.send(401);
});