I have a timeout with my application-level join between two documents : Thread and Message.
I am trying to get all the Messages of my Thread with this code:
router.get('/:themeId/threads/:threadId/messages', function(req, res, next) {
Thread.findById(req.params.threadId, function(err, thread) {
if (err) return next(err);
Message.find({ _id: { $in: thread.messages } }), function(err, message) {
if (err) return next(err);
res.json(message);
}
});
});
Unfortunately, I got a timeout with my request which I tested Postman.
I had this message when I tested it:
Could not get any response
There was an error connecting to
http://localhost:3000/api/themes/5b1bb59d4210c50cf798da57/threads/5b1bb5e84210c50cf798da59/messages.
Also I checked that thread.messages is an array with another request:
GET http://localhost:3000/api/themes/5b1bb59d4210c50cf798da57/threads/5b1bb5e84210c50cf798da59 :
The result is below and from my Threaddocument :
{
"numberOfViews": 0,
"numberOfComments": 0,
"numberOfLikes": 0,
"numberOfThanks": 0,
"messages": [
"5b1bb5ad4210c50cf798da58",
"5b1bb6464210c50cf798da5a"
],
"_id": "5b1bb5e84210c50cf798da59",
"theme": "5b1bb59d4210c50cf798da57",
"title": "Title azerty",
"createdAt": "2018-06-09T11:11:36.358Z",
"updatedAt": "2018-06-09T11:13:41.062Z",
"__v": 1
}
From my understanding, my request should do a find Message in my array of Thread.messages...
But it seems I miss something.
Any idea to solve my timeout request?
Thanks a lot for your help.
Couple of suggestions to try out:
Make sure thread.messages is not an empty array. You can do this by asserting that its length is greater than 0.
In the clause Message.find({ _id: { $in: thread.messages } }), cast the string values to objectids by before sending it to the find clause. So you can do
var myobj1 = [];
thread.messages.forEach(element => {myobj1.push(Mongoose.Types.ObjectId(element)})
I found a solution with the populate of Mongoose and theses sources :
http://mongoosejs.com/docs/populate.html
https://alexanderzeitler.com/articles/mongoose-referencing-schema-in-properties-and-arrays/
Below the modified code:
router.get('/:themeId/threads/:threadId/messages', function(req, res, next) {
Thread.findById(req.params.threadId, function(err, thread) {
if (err) return next(err);
Message.find({_id: { $in : thread.messages } } )
.populate('messages')
.exec(function(error, messages) {
res.json(messages);
});
});
});
Related
I am saving an updated array of _id's to an array on a document. If I check the document, everything is updating quite nicely, but when I populate right afterward using a new find query, it doesn't work right. populate wasn't working for me, so I decided to handle it manually and I am successful at filling them in, but they're in the wrong order.
export function sort_update(req, res) {
Action.findOneAndUpdate({
_id: req.query.action
}, {
child_actions: req.body.newArray
}, {
useFindAndModify: false, new: true
}, function(err, doc) {
if (err) return res.send(500, {
error: err
});
console.log("child action id strings after update", doc.child_actions); // ["1", "2"] correct!
Action.find({'_id': {$in: doc.child_actions }}, function(err, child_action_docs) {
if (err) return res.send(500, {
error: err
});
console.log("child action objects after fill", child_action_docs); // [{ _id: "2" }, { _id: "1" }] wrong!
doc.child_actions = child_action_docs;
res.send(doc);
});
});
}
Why are they in the wrong order? Does {'_id': {$in: doc.child_actions }} simply not guarantee any order at all? Do I have to re-sort my objects to the doc.child_actions order deliberately or is there a simpler way of telling mongodb to keep the order in the original array?
I'm trying to integrate an Excel spreadsheet with my application using an node.js Express Restful Api. My API already accepts simple json like:
{
"num": "1",
"name": "Adams"
}
But now i need to send array of objects like:
[
{
"num": 1,
"name": "Adams"
},
{
"num": 2,
"name": "Phillips"
}
]
I'm using mongoose to connect to a mongoDB server and already the following function connected to a route in my api to accept single objects:
create_a_budget: function (req, res) {
var budget = new budgetModel({
user_id : req.body.user_id,
seq_budget : req.body.seq_budget,
date_done : req.body.date_done,
num_budget : req.body.num_budget,
medium : req.body.medium,
client_name : req.body.client_name,
email : req.body.email
});
budget.save(function (err, budget) {
if (err) {
return res.status(500).json({
message: 'Error when creating budget',
error: err
});
}
return res.status(201).json(budget);
});
}
But i don't have a clue about how to treat the array
You can simply pass an array of documents received from mongodb in res.json. res.json() will handle array properly. You dont have to do anything else. Example of the same:-
db.budget.find(query, (err, budgets) {
if(err) {
// handle error
}
return res.status(200).json(budgets);
});
I have a collection of fixtures that 'belong' to a competitor and look something like this:
{
"_id": {
"$oid": "59dbdf6dbe628df3a80419bc"
},
"timeOfEntrance": "1507581805813",
"timeOfFinish": null,
"competitor": {
"$oid": "59db5a3f3d6119e69911a61a"
},
"__v": 0
}
My goal is to update only the document's timeOfFinish by sending a PUT request with competitor's ID as a param in the url and timestamp in the body. However I'm struggling to compose the update query.
The following is what I have currently, it never finds the right match and to my surprise it's always updating the wrong document.
fixtureController.put = (req, res) => {
const competitorId = req.params.id;
const timeOfFinish = req.body.timeOfFinish;
Fixture.findOne({'competitor.$oid': competitorId}, (err, fixture) => {
fixture.set({ timeOfFinish });
fixture.save()
.then(updatedFixture => {
return res.status(200).json({
success: true,
fixture: updatedFixture
})
})
.catch(err => {
return res.status(500).json({
message: err
});
});
});
};
Bit of a beginner in the MongoDB field, will appreciate your comments and solutions.
Turns out there was no need to specify the exact field in the match parameter. Mongoose matches by the id field automatically.
Fixture.findOne({'competitor': competitorId}, (err, fixture) => {
...
});
In mongodb there is a document like below,
{
"_id": ObjectId("57443657ee5b5ccc30c4e6f8"),
"name": "Kevin",
"email": "kevinwarn#gmail.com",
"password": "$2a$13$iZ0PhuY6VlBF6qC9rUredrG39Fw5pEKkIh.VCLiGsLPZMKYveyzey",
"mobile": "9980896745",
"__v": NumberInt(0),
"ocassionTypes": [
{
"occasiontype": "Anniversary",
"date": "2016-05-30T18:30:00.000Z"
},
{
"occasiontype": "Donation",
"date": "2016-07-24T18:30:00.000Z"
},
{
"occasiontype": "House Warming",
"date": "2016-09-21T18:30:00.000Z"
}
]
}
So I have written a query in Nodejs to search occasiontype element in ocassionTypes array like below,
router.post('/find-registry', function(req, res){
var uEmail = req.body.email;
var uocType = req.body.userOccasion;
var findUserId = function(db, callback) {
var cursor =db.collection('users').find({email:uEmail, ocassionTypes: {$elemMatch: {occasiontype:uocType}}}).toArray(function(err, docs1){
if(err){
callback(new Error("Some problem"));
} else {
callback(null,docs1);
}
});
};
MongoClient.connect(config.database, function(err, db) {
assert.equal(null, err);
findUserId(db, function(err,docs1) {
db.close();
if(err) return res.json({result:null})
else
return res.json({result1:docs1});
});
});
});
Using this query I am getting 0th index element, but if I give 1st and 2nd element it always shows only 0th index in the output.
In front end I have given input as shown in the picture below.
file.html
Is there any wrong in my query? please help me to fix this.
your query is right but it will give matched document with full array
just add projection in your query
db.collection('users').find({email:uEmail, ocassionTypes: {$elemMatch: {occasiontype:uocType}}},{email:1, ocassionTypes: {$elemMatch: {occasiontype:uocType}}})
If you are searching in sub document, mongodb returns all sub-document instead of matched sub-document. You can limit no. of sub-document using following code.
var cursor =db.collection('users').find({email:uEmail, ocassionTypes: {$elemMatch: {occasiontype:uocType}}},{email: 1, ocassionTypes: {$elemMatch: {occasiontype: uocType}}}).toArray(function(err, docs1){
if(err){
callback(new Error("Some problem"));
} else {
callback(null,docs1);
}
});
It is not tested but it should work.
I am learning mongodb, node.js and mongoose and want to update a mongodb and then display it on my browser. However my code only displays the results prior to my update even though I know the database has already been updated.
So for example I have two students called John and Tom, but when I update it with a third student called Fred and try to render the results, it only gives me John and Tom's details. Here is my code:
create: function(req, res) {
console.log('creating model');
var newStud = new Models.Student({
surname: req.body.surname,
firstname: req.body.firstname,
}
);
console.log('saving model');
newStud.save();
console.log('rendering model');
Models.Student.find({},
function(err,result){
console.log('finding results');
if (err) {
throw err;}
else {
console.log('returning results');
res.send(result);
}
}
);
},
When I update it with Fred's details, the console outputs the following:
creating model
saving model
rendering model
finding results
returning results
POST /students 200 21.629 ms - 5195
but the page only shows the following:
[
{
"surname": "Smith",
"firstname":"John"
"_id": "55bed36461521187445e5b53",
"__v": 0
},
{
"surname": "Peters",
"firstname":"Tom",
"_id": "55bed3f6c4faaa63464fc6df",
"__v": 0
},
]
I suspect my callback is not working properly. Can anyone explain why? Any help is most appreciated.
The problem here is of course that .save() is an asynchronous method in itself. So to need to wait for it to respond before asking for data from the collection. Otherwise, it likely has not actually created the new item yet:
create: function(req, res) {
console.log('creating model');
var newStud = new Models.Student({
surname: req.body.surname,
firstname: req.body.firstname,
}
);
console.log('saving model');
newStud.save(function(err,doc) { // <-- callback here
console.log('rendering model');
Models.Student.find({},
function(err,result){
if (err) {
throw err;}
else {
console.log('returning results');
res.send(result);
}
}
);
});
});
So basically you need to "wait" for the other .save() action to respond before you go query the whole collection to see the new addition.