I have two tables users (fields: name, age) and links (fields: title, url, userId(ref to users)). There is a one-to-many relation between users to links. Now I want to run a query like : select * from links where user has age more than 26.
I have been trying with query like :
Links
.find({title:'Chemistry'})
.populate({
path: 'userId',
select: 'name.first age -_id',
match: {age: {$gte: 26}}
})
.exec( function(err,data) {
if (err) console.log( err );
console.log( 'data', data);
res.jsonp(data);
});
This gives me the following result :
[
{
_id: "54037d00e74f00f917e709ff",
title: "Chemistry",
url: "http://chemistry.com",
comment: "Great chemo slides",
favourites: "507",
userId: {
name: {
first: "Bob"
},
age: 31
},
tags: [
"tutorials",
"chemo"
]
},
{
_id: "540457f2557cded82b331ee2",
title: "Chemistry",
url: "http://chemistry.com",
comment: "Great chemo slides",
favourites: "507",
userId: null,
tags: [
"tutorials",
"chemo"
]
}
]
Notice that the userId is null in the second object. I am not sure my query is right, but I think it should be a simple enough query for mongodb to support it. I probably don't know how to do it, do you have any idea about this ? Thanks.
Related
This is my Conversation Schema
const ConversationSchema = new Schema({
recipients: [{ type: Schema.Types.ObjectId, ref : 'User' }],
lastMessage: {
type: String,
default: ''
},
date: {
type: Date,
default: Date.now()
},
})
I want to know if there exist an array [ patientId, doctorId ]
Here is my main approach to find
I am not able to get the response and I already have one document with that same array
const conversationBetween = await Conversation.findOne(
{
recipients: {
$all: [
{ $elemMatch: { $eq: patientId }},
{ $elemMatch: { $eq: doctorId }}
],
}
}
)
if (conversationBetween) {
return res.status(401).json({
status: "failed",
message: "You already have a conversation with this doctor"
});
}
following Code to add a Conversation in the Conversation Collection, this works fine
const newConversation = new Conversation({
recipients: [ patientId,doctorId ],
lastMessage: `I want to get consultation`,
date: Date.now(),
})
await newConversation.save()
res.status(200).json({
status: "success",
message: "Conversation added successfully",
conversation: newConversation
});
The main purpose is to make sure that if there present an entry with [ patientId, doctorId ] in Conversation it should not make a new entry..
But at this time its not able to find and is making that same entry.
You can do this
await Conversation.findOne(
{
recipients: [patientId, doctorId]
}
)
Working in Playground
I have a model in mongodb that looks something like this...
{
username: 'bob',
user_id: '12345',
post: 'Hey everyone, this is my post',
photoID: RANDOM_GENERATED_NUMBER, // each user has their own photoID
comments: [
{
username: 'tom',
user_id: '54321',
post: 'Hey everyone, this is comment 1',
photoID: RANDOM_GENERATED_NUMBER, // each user has their own photoID
responses: [
{
username: 'bob',
user_id: '12345',
post: 'Hey everyone, this is response 2',
photoID: RANDOM_GENERATED_NUMBER, // each user has their own photoID
},
{
username: 'will',
user_id: '35791',
post: 'Hey everyone, this is response 2',
photoID: RANDOM_GENERATED_NUMBER, // each user has their own photoID
}
]
},
{
username: 'bob',
user_id: '12345',
post: 'Hey everyone, this is comment 2',
photoID: RANDOM_GENERATED_NUMBER, // each user has their own photoID
responses: []
}
]
}
On my site, everytime a user changes their profile picture, they get a new 'photoID', referencing the picture, so it can easily be displayed with their username above any posts they make. Because of this, when a user updates their profile picture and gets a new 'photoID', I need to be able to make a query to this 'Post' model that searches for any 'posts', 'comments' or 'responses' that were posted by 'bob'. I then need to update the photoID for that 'post', 'comment' or 'response'.
Is there a query I can use to do this?
You need two queries to do that task:
Update photoID in subdocuments:
https://mongoplayground.net/p/jTb3qDxIHL1
db.collection.update({},
{
$set: {
"comments.$[c].photoID": "NEW_RANDOM_GENERATED_NUMBER",
"comments.$[].responses.$[r].photoID": "NEW_RANDOM_GENERATED_NUMBER",
},
},
{
multi: true,
arrayFilters: [
{
"c.user_id": "12345",
},
{
"r.user_id": "12345",
},
],
})
Update photoID in document root:
https://mongoplayground.net/p/-Bm4Oykz-1E
db.collection.update({
user_id: "12345"
},
{
$set: {
photoID: "NEW_RANDOM_GENERATED_NUMBER",
}
},
{
multi: true,
})
I have a collection schema like this:
const PrescriptionSchema = new Schema({
patientId:{type: mongoose.Schema.ObjectId, ref: 'User'},
prescriptionName: String,
prescriptionNote: String,
prescriptionDate: Date,
diseaseId: {type: mongoose.Schema.ObjectId, ref: 'Diseases'},
drugs: [{
drugcateId:{type: mongoose.Schema.ObjectId, ref: 'DrugCategory'},
quantity: Number,
howtouse: String
}],
is_deleted: {type: Boolean, default: false},
createdBy: {type: mongoose.Schema.ObjectId, ref: 'User'}
}, {
timestamps: true,
collection: 'prescriptions'
}
);
export default mongoose.model('prescriptions', PrescriptionSchema );
Note that in this collection I have an array of "drugs", this is an array of drug that I get from 'DrugCategory', in each drug I have quantity and howtouse..so that I group it (drugCateId, quantity, howtouse) in drugs array.
When I find a prescription, I want to populate drugCateId inside drugs array. How can I do it?
Below is my current code:
async findOne(req, res){
const { id } = req.params;
await Prescriptions.
findOne({ is_deleted: false, _id: id}).
.populate(
{
path: 'drugs',
populate: {
path: 'drugCateId',
model: 'DrugCategory'
}
}).
exec(function (err, data) {
if (err) return handleError(err);
res.send(data)
});
}
But it's not work.
Below is my result:
{
"is_deleted": false,
"_id": "5f32768a06693a520806717d",
"patientId": "5c80930d447df7735138693e",
"prescriptionName": "Prescription for you",
"prescriptionNote": "Please drink follow doctor",
"prescriptionDate": "2020-07-08T00:00:00.000Z",
"diseaseId": "5f22a6d600980c081ca9e14f",
"drugs": [
{
"_id": "5f32768a06693a5208067181",
"drugcateId": "5f23deca04e3150a48632229", // How can I populate this one?
"quantity": 10,
"howtouse": "drink 2 times after meal everyday"
},
{
"_id": "5f32768a06693a5208067180",
"drugcateId": "5f23deca04e3150a48632233", // How can I populate this one?
"quantity": 10,
"howtouse": "drink 2 times after meal everyday"
},
{
"_id": "5f32768a06693a520806717f",
"drugcateId": "5f23deca04e3150a48632234", // How can I populate this one?
"quantity": 10,
"howtouse": "drink 2 times after meal everyday"
},
{
"_id": "5f32768a06693a520806717e",
"drugcateId": "5f23deca04e3150a4863224a", // How can I populate this one?
"quantity": 10,
"howtouse": "drink 2 times after meal everyday"
}
],
"createdBy": "5d1cd947231ceb95b8838c1b",
"createdAt": "2020-08-11T10:44:26.842Z",
"updatedAt": "2020-08-11T10:44:26.842Z",
"__v": 0
}
I hope you understand my issue, please take a look. Thanks you
You were very close it seems, but make sure to give the proper path:
.populate({
path: 'drugcateId',
model: 'DrugCategory'
})
Change drugCateId to drugcateId.
Also, you should be able to directly populate DrugCategory.
Your current version does not match your schema. It suggest you want to populate both drugs and drugs.drugcateId. But here drugs are embedded directly and not references to documents in another collection, so it's not possible to populate():
.populate({
path: 'drugs', // this assumes drugs are objectIds: [{ type: ObjectId, ref: 'Drug' }]
populate: {
path: 'drugCateId',
model: 'DrugCategory'
}
})
Instead, you should be able to use dot-notation for arrays:
.populate({ path: "drugs.drugcateId" })
or short
.populate("drugs.drugcateId")
Thanks you for your reply. I have a mistake that my model is "drugcate" but in my populate command is "drugCate". I already change my model to "drugCate" and bellow query is worked.
populate({ path: 'drugs.drugCateId',
populate: {path: 'drugs.drugCateId'}
})
Thanks
I currently have the the collection "Plans" and it is made upon the creation of a form submit. It inserts the following:
Plans.insert({
location,
address,
date,
time,
notes,
createdAt: new Date(), // current time
owner: Meteor.userId(),
username: Meteor.user().username,
attendees: [
{
attender: [{
user: String,
attending: Boolean,
}],
},
],
});
Then, upon a click of a checkbox, I want a new attender object to be added to the attendees array. So far I have tried to do:
'click .notattending'() {
Plans.insert(
{_id: this._id,
attendees: [{
attender: [
{
user: Meteor.user().username,
attending: false,
}
],
}
]
},
);
},
However it isn't adding to the Mongo collection. Is this the correct way to go about doing it?
You can try this to based on your schema.
Plans.update({ _id: this._id }, {
$push: {
attendees: { user: "", attending: true },
},
});
In the docs of waterline it is stated that this is the way to perform a IN query on a model:
Model.find({
name : ['Walter', 'Skyler']
});
And this the way to perform an OR query on a model:
Model.find({
or : [
{ name: 'walter' },
{ occupation: 'teacher' }
]
})
My problem now is that i need a combination of those two, and to make it even more complicated, one of the attributes i have to use is a collection.
So what i tried is this, but it doesn't seem to work:
Product.find({
or : [
{ createdBy: userIds },
{ likes: userIds }
]
})
Note: userIds is an array of id's from a user model.
The (simplified) product model looks likes this:
module.exports = {
attributes: {
name: 'string',
description: 'string',
createdBy: {
model: 'User'
},
brand: {
model: 'Brand',
},
likes: {
collection: 'User',
}
}
}
The query works when I only include createdBy, so it seems to be a problem with the collection attribute.
Is this somehow possible?
Thank you for your input.
UPDATE:
I think this is only possible with native() queries.
The way I understand it something like this should work.
Product.native(function(err, products){
if(err) return res.serverError(err);
products.find({"likes": { $elemMatch: { _id: { $in: userIds}}}}).toArray(function(err, results){
if (err){
console.log('ERROR', err);
}
else {
console.log("found products: " + results.length);
console.log(results);
return res.ok(results);
}
});
});
Unfortunately, it doesn't. The returned results is always an empty array.