Mongoose query to multiple values - node.js

So I have a Mongoose query question that I can't seem to figure out. I'm trying to query a schema to find all documents in the collection that have a parameter specified user id in one of a few places... What I have so far is this:
Schema:
var Module = new Schema({
template: { type: Schema.ObjectId, ref: 'template' },
owner: { type: String, required: true, index: { unique: false } },
primary: { type: Schema.ObjectId, ref: 'User' },
users: [{ type: Schema.ObjectId, ref: 'User' }],
data: [],
children: [{ type: Schema.ObjectId, ref: 'Module' }],
parent: { type: Schema.ObjectId, ref: 'Module' }
});
Query:
Module.find()
.or([{owner: req.user.id}, {primary: req.user.id}])
.populate('primary users children parent template')
.exec(function (err, modules) {
...
}
So as of now, it seems to correctly find documents that have the req.user.id as the primary or owner field, but how would I also return all documents where the users array is also searched for this value?
Thanks!

Related

I want to list users and all user's comments in MongoDB. Is it possible?

I want to list the users and search for comments in another collection using the same query.
That's my users Schema:
Schema({
cod: {
type: String,
require: true
},
name: {
type: String,
required: true
}
})
And that's my comments Schema:
Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'users'
},
post: {
type: Schema.Types.ObjectId,
ref: 'posts'
},
comment: {
type: String,
required: true
}
})
I want get some like this:
{
_id: 5eee97c18b83e338bcbfa8f9,
name: 'Cool Name',
cod: 'CN001',
comments: [{
_id: ObjectId(...)
post: ObjectId(...),
comment: 'comment 1'
},
{
_id: ObjectId(...)
post: ObjectId(...),
comment: 'comment 2'
}
]
}
is it possible?
Thank you!
you might need to change your schema to:
Users:
Schema({
cod: {
type: String,
require: true
},
name: {
type: String,
required: true
},
comments: {
type: Schema.Types.ObjectId,
ref: 'comments'
}
})
Comments:
Schema({
post: {
type: Schema.Types.ObjectId,
ref: 'posts'
},
comment: {
type: String,
required: true
},
user: { // in case you want to query comments and populate the user
type: Schema.Types.ObjectId,
ref: 'users'
}
})
Then query:
users.findById({'your user id here'})
.populate({path:'comments',select:['post','comment']})
.then((response)=>{
// do anything you want with the data here
})

mongoose: Populating a discriminated subdocument

I want to populate the fields of a subdocument, which is a discriminated element of a common Schema (Notificationable discriminated into Message or FriendRequest).
This question is quite similar to this one: mongoosejs: populating an array of objectId's from different schemas, which was not solved two years ago. Since mongoose evolved, and discriminator also, I am asking the question again.
What I have tried so far:
Notification.find({_id: 'whatever'})
.populate({
path: 'payload',
match: {type: 'Message'},
populate: ['author', 'messageThread']
})
.populate({
path: 'payload',
match: {type: 'FriendRequest'},
populate: ['to', 'from']
})
.exec();
This does not work, because the path is the same.
So I tried:
Notification.find({_id: 'whatever'})
.populate({
path: 'payload',
populate: [
{
path: 'messageThread',
match: {type: 'Message'},
},
{
path: 'author',
match: {type: 'Message'},
},
{
path: 'from',
match: {type: 'FriendRequest'},
},
{
path: 'to',
match: {type: 'FriendRequest'},
},
]
})
.exec();
Which does not work either, maybe because the match is executed in the subdocument and thus does not have a field type.
Is there any solution for this?
Here are my (main) models, I did not provide User or MessageThread.
The main document:
const NotificationSchema = new Schema({
title: String,
payload: {
type: Schema.Types.ObjectId,
ref: 'Notificationable'
});
mongoose.model('Notification', NotificationSchema);
The payload Parent schema
let NotificationableSchema = new Schema(
{},
{discriminatorKey: 'type', timestamps: true}
);
mongoose.model('Notificationable', NotificationableSchema);
And the two discriminated possibilities:
let Message = new Schema({
author: {
type: Schema.Types.ObjectId,
ref: 'User'
},
messageThread: {
type: Schema.Types.ObjectId,
ref: 'MessageThread'
}
}
Notificationable.discriminator('Message', Message);
And:
let FriendRequest = new Schema({
from: {
type: Schema.Types.ObjectId,
ref: 'User'
},
to: {
type: Schema.Types.ObjectId,
ref: 'User'
}
}
Notificationable.discriminator('FriendRequest', FriendRequest);

How to remove left-over ObjectId?

The problem is:
I have a collection of photos schema and likes schema, and inside photos there is an array of like ObjectIds called likeArray which is used to populate data from likes colletion.
But when i delete a like from likes collection, the ObjectId of that like in the likeArray still exists.
I tried to find the index of like._id in the likeArray and use likeArray.splice(index, 1) but couldn't work.
Can someone know the solution?
Here's the photo schema:
var Photo = mongoose.model('Photo', new mongoose.Schema({
photo_url: String,
photo_description: String,
user:{
id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
},
username: String,
profile_photo: String
},
comments: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'comment'
}
],
likes: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'like'
}
],
created_at: {type: Date, default: Date.now}
}));
Here's the Like schema:
var Like = mongoose.model('Like', new mongoose.Schema({
user_id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
},
photo_id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'photo'
},
created_at: {type: Date, default: Date.now}
}));
Instead of splice you can use $pull operator. Here's how it'd look in mongo shell.
db.likes.remove({_id: like_oid});
db.photos.update({likes: like_oid}, {$pull: {likes: like_oid}}, { multi: true });

Mongoose populate array of object ids

I'm trying to populate my Thread schemas GET response with all the comments related that that specific thread. I've specified a path within the Thread model to accept an array of Comments that I'll then populate when I request a thread, but it's continuing to be empty.
I'm not sure if I then need to push all the comments into the thread, but I think with the way I'm doing it, it's not required? I'm using Mongoose 4.4.19. I've followed along with the docs but still can't figure out where I've gone wrong.
Thread Schema:
const threadSchema = new Schema({
user: {
type: Schema.ObjectId,
ref: 'User',
required: true
},
title: {
type: String
},
content: {
type: String
},
category: {
type: String
},
comments: [{
type: Schema.ObjectId,
ref: 'Comment'
}]
}, {
timestamps: true
})
Comment Schema:
const commentSchema = new Schema({
user: {
type: Schema.ObjectId,
ref: 'User',
required: true
},
thread: {
type: Schema.ObjectId,
ref: 'Thread',
required: true
},
content: {
type: String
}
}, {
timestamps: true
})
Handles get requests:
export const index = ({ querymen: { query, select, cursor } }, res, next) =>
Thread.find(query, select, cursor)
.populate('user comments')
.then(threads => threads.map(thread => thread.view()))
.then(success(res))
.catch(next)

How filter sub sub document in MongoDB

Hello I am working with the full Stack 'MEAN' and i have a data structure in MongoDB as indicated below:
var ExpenseSchema = new Schema({
date: {
type: Date,
default: Date.now,
required: 'Ingrese la fecha del comprobante'
},
supplier: {
type: Schema.ObjectId,
ref: 'Supplier',
},
created: {
type: Date,
default: Date.now
},
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
var SupplierSchema = new Schema({
name: {
type: String,
default: '',
required: 'Ingrese la Razon Social del Proveedor',
trim: true
},
category: {
type: Schema.ObjectId,
ref: 'Category',
},
created: {
type: Date,
default: Date.now
},
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
var CategorycompraSchema = new Schema({
name: {
type: String,
default: '',
required: 'Please fill Rubrocompra name',
trim: true
},
created: {
type: Date,
default: Date.now
},
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
Each 'Expense' has a 'Supplier' and each supplier has a 'Category'
I need to query so that I filter all 'Expenses' in a particular category. Someone could tell me how this can be done with MongoDB or mongoose?
That is an important case in mongodb, aggregations in mongodb is the right approach to solve this. You need to $unwind the supplier array and then category array and then use $group to put it back together:
My solution may differ depending upon your requirement, but this is something you have to do:
db.test.aggregate(
{ $match: {...}}, //match query
{ $unwind: '$supplier'},
{ $unwind: '$supplier.category'},
{ $match: {supplier.category.a: ...}}, //match query after unwinding of supplier and category
{ $group: {_id: '$_id', ...})
It will first unwind the supplier array and then unwind category array
But since you are also using mongoose, you can use plain JavaScript. You can fetch all expenses and then loop through them and
obtain your result
Expense.find().then(function(expenses) {
expenses.forEach(function(suppliers){
suppliers.forEach
...
})
})
Although this javascript way would increase effort in single threaded enviroment(node js), but still it comes in handy for some typical mongodb queries

Resources