Mongoose populated documentation:
Model.findOne().populate('author').exec(function (err, doc) {
console.log(doc.author.name) // Dr.Seuss
console.log(doc.populated('author')) // '5144cf8050f071d979c118a7'
})
My code:
Job.find({operator: user.operator, status: {$nin: ['assigned', 'unassigned', 'completed']}})
.populate('version', 'results.routes')
.exec(function(err, jobs)
{
console.log(jobs.populated('version'))
...
I have been getting this error when the code runs:
TypeError: jobs.populated is not a function
Why am I getting this error? What am I doing wrong here? Thanks in advance.
EDIT: Posting Job model:
var JobSchema = new Schema(
{
created: Date,
received: Date,
due_date: Date,
freight: Number,
creator: { type: mongoose.Schema.ObjectId, ref: 'User' },
operator: { type: mongoose.Schema.ObjectId, ref: 'Operator' },
routing: { type: mongoose.Schema.ObjectId, ref: 'Routing' },
version: {
type: mongoose.Schema.ObjectId, ref: 'Version',
validate: [validateStarredVersion, 'You must star this route before monitoring it.']
},
...
The version model:
var VersionSchema = mongoose.Schema(
{
routing: { type: mongoose.Schema.ObjectId, ref: 'Routing' },
name: String,
number: Number,
date: Date,
tags: [String],
results:
{
routes:
[ resultSchema ],
...
resultsSchema:
var resultSchema = new Schema(
{
name: String,
vehicle: mongoose.Schema.Types.Mixed,
distance: Number,
weight: Number,
volume: Number,
capacity_weight: Number,
capacity_volume: Number,
occupancy_weight: Number,
occupancy_volume: Number,
job: { type: mongoose.Schema.ObjectId, ref: 'Job' },
operator: mongoose.Schema.Types.Mixed,
delivery_order:
[
{
delivery: mongoose.Schema.Types.Mixed,
depot: mongoose.Schema.Types.Mixed,
arrival_time: Date
}
],
directions: [ directionSchema ]
});
I have not edited with the entired object because it's too large. I put only the related information.
The documentation uses findOne(), while your code uses find(). This means the variable jobs isn't a mongoose document, but an array of mongoose documents. The native Array doesn't have a method .populated()
Related
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
})
I'm new to building rest api's with mongoose and express and have a question on how to use refPath correctly on my Models files and allowing for an array of items.
Below I have included the code for a model (built thus far) and would love any input on if I'm even close to building this correctly.
I will also include a screenshot that visually depicts the relationships I'm trying to create.
Those who answer questions here are GODS and I appreciate all the help this community has given me over the years!
const mongoose = require("mongoose");
const slugify = require("slugify");
const AlertSchema = new mongoose.Schema({
parentId: {
type: mongoose.Schema.ObjectId,
required: true,
refPath: "parentModel",
},
parentModel: {
type: String,
required: true,
enum: ["orgs", "clients"],
},
status: { type: String, default: "no-status" },
departments: [{ type: mongoose.Schema.Types.ObjectId, ref: "orgs" }],
createdAt: { type: Date, default: Date.now },
createdByType: [{ type: mongoose.Schema.Types.ObjectId, ref: "users" }],
createdById: [{ type: mongoose.Schema.Types.ObjectId, ref: "users" }],
groups: [{ type: String, default: "unGrouped" }],
stage: [{ type: mongoose.Schema.Types.ObjectId, ref: "stages" }],
children: { type: String },
resource: {
type: String,
match: [
/https?:\/\/(www\.)?[-a-zA-Z0-9#:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()#:%_\+.~#?&//=]*)/,
"Please use a valid URL with HTTP or HTTPS",
],
},
notes: [{ type: mongoose.Schema.Types.ObjectId, ref: "notes" }],
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: "comments" }],
priority: { type: String },
assignedTo: [{ type: mongoose.Schema.Types.ObjectId, ref: "users" }],
title: {
type: String,
required: [true, "Please add a title"],
maxlength: [50, "Title cannot be more than 50 characters"],
},
message: {
type: String,
required: [true, "Please add a message"],
maxlength: [500, "Message cannot be more than 500 characters"],
},
slug: String,
});
//create alert slug from the title
AlertSchema.pre("save", function (next) {
console.log("Slugify Ran", this.name);
this.slug = slugify(this.title, { lower: true });
next();
});
module.exports = mongoose.model("Testalert", AlertSchema);
Desired relationships diagram:
My schema is as shown below:
const order = new Schema({
order_status: Number,
foodtruck_id: { type: Schema.Types.ObjectId, ref: 'foodtruck' },
customer_id: { type: Schema.Types.ObjectId, ref: 'user' },
items: [{ type: Schema.Types.ObjectId, ref: 'items' }],
user_type: Boolean,
order_time: Date,
order_rating: { type: Number, default: 5.0 },
order_issue_comments: String,
order_special_instruction: String,
order_total: Number,
order_location: String,
order_coupon_code: String,
payment_id: { type: Schema.Types.ObjectId, ref: 'payment' },
order_meta: { type: Schema.Types.Mixed, ref: 'order_sub_info', default: {} }
}, { versionKey: false }, { minimize: false });
my query is as shown below:
order.find({
'foodtruck_id': foodtruck_id.trim()
}).populate('customer_id', {
'_id': 1,
'user_name': 1,
'email_id': 1,
'ph_no': 1,
'login_type': 1
}).populate('items').
populate('order_meta', 'order_otp').exec((err, orderList) => {
if (err) res.json({
status: '500',
message: err
});
else {
console.log("called");
res.json({
status: '200',
message: 'Order list',
data: orderList
});
}
});
For this query,it is giving me Cast to ObjectId failed for value at path _id as order_meta has default value {}. How to have effective populate query so that It can take care of this testcase?
It is not good idea to put empty object in a place, where reference id is expected. Both - for having problem with populate and for common sense too (if it is field which has reference, it should be null/undefined or reference itself).
It is common that you want to transform your data at some endpoint, but it should not interfere with database or business logic of application.
You can defined toJSON method that should be used for your model. In your case
const order = new Schema({
order_status: Number,
foodtruck_id: { type: Schema.Types.ObjectId, ref: 'foodtruck' },
customer_id: { type: Schema.Types.ObjectId, ref: 'user' },
items: [{ type: Schema.Types.ObjectId, ref: 'items' }],
user_type: Boolean,
order_time: Date,
order_rating: { type: Number, default: 5.0 },
order_issue_comments: String,
order_special_instruction: String,
order_total: Number,
order_location: String,
order_coupon_code: String,
payment_id: { type: Schema.Types.ObjectId, ref: 'payment' },
order_meta: { type: Schema.Types.ObjectId, ref: 'order_sub_info'}
}, { versionKey: false }, { minimize: false });
order.options.toJSON = {
transform(zipRequestDocument, ret, options) { // eslint-disable-line no-unused-vars
if (!ret.order_meta){
ret.order_meta = {};
}
},
};
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 });
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