Sequelize limit order issue - node.js

Currently am having a problem with a simple query.
Sequelize query:
db[TABLE_NAMES.BOOKING].findAll({
order: [
[ db[TABLE_NAMES.USER_BOOKING_RELATION], db[TABLE_NAMES.BOOKING_STATUS], sequelize.literal('status = \'Attention\''), 'desc'],
['created_at', 'desc']
],
offset,
limit: max,
attributes: ['id', 'created_at'],
where: { school_id: schoolId },
include: [
{
attributes: ['id'],
model: db[TABLE_NAMES.USER_BOOKING_RELATION],
include: [
{
required: true,
attributes: ['status'],
model: db[TABLE_NAMES.BOOKING_STATUS],
where: { status: { [Sequelize.Op.in]: ['Attention', 'Pending', 'Invited'] } }
},
]
}
]
});
Models
const booking = sequelize.define(TABLE_NAMES.BOOKING, {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
unique: true
},
created_at: {
type: DataTypes.DATE,
defaultValue: sequelize.literal('NOW()')
},
updated_at: {
type: DataTypes.DATE,
defaultValue: sequelize.literal('NOW()')
},
deleted_at: {
type: DataTypes.DATE
}
});
const user_booking_relation = sequelize.define(TABLE_NAMES.USER_BOOKING_RELATION, {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
unique: true
},
user_id: {
type: DataTypes.UUID,
allowNull: false
},
booking_id: {
type: DataTypes.UUID,
allowNull: false
},
booking_status_id: {
type: DataTypes.UUID,
allowNull: false,
},
created_at: {
type: DataTypes.DATE,
defaultValue: sequelize.literal('NOW()')
},
updated_at: {
type: DataTypes.DATE,
defaultValue: sequelize.literal('NOW()')
},
deleted_at: {
type: DataTypes.DATE
},
});
const booking_status = sequelize.define(TABLE_NAMES.BOOKING_STATUS, {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
unique: true
},
status: {
type: DataTypes.STRING,
allowNull: false,
unique: true
},
created_at: {
type: DataTypes.DATE,
defaultValue: sequelize.literal('NOW()')
},
updated_at: {
type: DataTypes.DATE,
defaultValue: sequelize.literal('NOW()')
},
deleted_at: {
type: DataTypes.DATE
}
});
booking.hasMany(user_booking_relation, { foreignKey: 'booking_id', sourceKey: 'id' });
user_booking_relation.belongsTo(booking, { foreignKey: 'booking_id', targetKey: 'id' });
booking_status.hasMany(user_booking_relation, { foreignKey: 'booking_status_id', sourceKey: 'id' });
user_booking_relation.belongsTo(booking_status, { foreignKey: 'booking_status_id', targetKey: 'id' });
Generated sql
SELECT `booking`.*,
`user_booking_relations`.`id` AS `user_booking_relations.id`,
`user_booking_relations->booking_status`.`id` AS `user_booking_relations.booking_status.id`,
`user_booking_relations->booking_status`.`status` AS `user_booking_relations.booking_status.status`
FROM (SELECT `booking`.`id`, `booking`.`created_at`
FROM `booking` AS `booking`
WHERE (`booking`.`deleted_at` IS NULL AND `booking`.`school_id` = 'a97b42e5-c864-4a4a-870b-737dd9700124')
AND (SELECT `user_booking_relations`.`booking_id`
FROM `user_booking_relation` AS `user_booking_relations`
INNER JOIN `booking_status` AS `booking_status`
ON `user_booking_relations`.`booking_status_id` = `booking_status`.`id` AND
(`booking_status`.`deleted_at` IS NULL AND
`booking_status`.`status` IN ('Invited', 'Pending', 'Attention'))
WHERE ((`user_booking_relations`.`deleted_at` IS NULL) AND
`user_booking_relations`.`booking_id` = `booking`.`id`)
LIMIT 1) IS NOT NULL
ORDER BY `booking`.`created_at` DESC
LIMIT 0, 10) AS `booking`
LEFT OUTER JOIN ( `user_booking_relation` AS `user_booking_relations` INNER JOIN `booking_status` AS `user_booking_relations->booking_status` ON
`user_booking_relations`.`booking_status_id` = `user_booking_relations->booking_status`.`id` AND
(`user_booking_relations->booking_status`.`deleted_at` IS NULL AND
`user_booking_relations->booking_status`.`status` IN ('Invited', 'Pending', 'Attention')) )
ON `booking`.`id` = `user_booking_relations`.`booking_id` AND
(`user_booking_relations`.`deleted_at` IS NULL)
ORDER BY `user_booking_relations->booking_status`.status = 'Attention' DESC, `booking`.`created_at` DESC;
Result
// first page
// first page
[
{
"id": "4c74c307-3f7c-40c6-ba26-6d0e9f510bcc",
"created_at": "2020-05-30T20:15:07.000Z",
"user_booking_relations": [
{
"id": "7cb183c7-77cf-4fc8-9c98-eb2b8abf8d39",
"booking_status": {
"status": "Attention"
}
}
]
},
{
"id": "1e8c9250-61b5-4610-b913-bd7aee866d5d",
"created_at": "2020-06-01T14:48:00.000Z",
"user_booking_relations": [
{
"id": "0a9ba1a0-0929-4979-ba15-12c4903fd8a5",
"booking_status": {
"status": "Invited"
}
},
]
},
{
"id": "a1624f59-ebaa-4bc7-95b8-d0e96c1ec917",
"created_at": "2020-06-01T08:45:12.000Z",
"user_booking_relations": [
{
"id": "fdbc677b-2035-44d2-8d9a-ab304e5624ee",
"booking_status": {
"status": "Pending"
}
}
]
}
]
// second page
[
{
"id": "d18abf5c-c986-4c2c-a08d-02e1488745d8",
"created_at": "2020-05-30T20:14:10.000Z",
"user_booking_relations": [
{
"id": "585c0674-13cf-45ac-91bc-087b345a7b31",
"booking_status": {
"status": "Attention"
}
}
]
},
{
"id": "692ccef9-12b4-4aed-955b-11ce65512469",
"created_at": "2020-05-30T20:12:45.000Z",
"user_booking_relations": [
{
"id": "5c3d214d-833a-482d-aeb5-272af750f3bb",
"booking_status": {
"status": "Attention"
}
}
]
},
{
"id": "1a5a56a9-4a6e-4548-a4d8-b388e6a9ac02",
"created_at": "2020-05-30T20:09:43.000Z",
"user_booking_relations": [
{
"id": "cea240f4-2529-44ae-a82d-f53d2dbbd0fc",
"booking_status": {
"status": "Attention"
}
}
]
}
]
Expected result
// first page
[
{
"id": "4c74c307-3f7c-40c6-ba26-6d0e9f510bcc",
"created_at": "2020-05-30T20:15:07.000Z",
"user_booking_relations": [
{
"id": "7cb183c7-77cf-4fc8-9c98-eb2b8abf8d39",
"booking_status": {
"status": "Attention"
}
}
]
},
{
"id": "d18abf5c-c986-4c2c-a08d-02e1488745d8",
"created_at": "2020-05-30T20:14:10.000Z",
"user_booking_relations": [
{
"id": "585c0674-13cf-45ac-91bc-087b345a7b31",
"booking_status": {
"status": "Attention"
}
}
]
},
{
"id": "692ccef9-12b4-4aed-955b-11ce65512469",
"created_at": "2020-05-30T20:12:45.000Z",
"user_booking_relations": [
{
"id": "5c3d214d-833a-482d-aeb5-272af750f3bb",
"booking_status": {
"status": "Attention"
}
}
]
}
]
// second page
[
{
"id": "1a5a56a9-4a6e-4548-a4d8-b388e6a9ac02",
"created_at": "2020-05-30T20:09:43.000Z",
"user_booking_relations": [
{
"id": "cea240f4-2529-44ae-a82d-f53d2dbbd0fc",
"booking_status": {
"status": "Attention"
}
}
]
},
{
"id": "1e8c9250-61b5-4610-b913-bd7aee866d5d",
"created_at": "2020-06-01T14:48:00.000Z",
"user_booking_relations": [
{
"id": "0a9ba1a0-0929-4979-ba15-12c4903fd8a5",
"booking_status": {
"status": "Invited"
}
},
]
},
{
"id": "a1624f59-ebaa-4bc7-95b8-d0e96c1ec917",
"created_at": "2020-06-01T08:45:12.000Z",
"user_booking_relations": [
{
"id": "fdbc677b-2035-44d2-8d9a-ab304e5624ee",
"booking_status": {
"status": "Pending"
}
}
]
}
]
As we can see from the generated SQL, bookings with any of those statuses are initially selected and then sorted. I need Attention bookings to go first. How can I get around this or fix it? Any thoughts will be much appreciated.
Thanks,
Alex.

Related

Full text Search returns empty array using mongoose and Node.js

None of the other SO articles got me a solution.
Schema Definition:
const jobSchema = new (require("mongoose").Schema)(
{
userID: { type: require("mongoose").Schema.Types.ObjectId, ref: "User" },
emailID: { type: String, trim: true, required: false },
jobTitle: { type: String, trim: true, required: false },
jobDescription: { type: String, trim: true, required: false },
company: { type: String, required: false },
position: { type: String, required: false },
noOfYearsExperience: { type: String, required: false },
domain: { type: String, required: false },
link: { type: String, required: false },
location: { type: String, required: false },
jobCreationStatus: { type: String, required: false },
isActive: { type: Boolean, default: true, required: false },
isFeatured: { type: Boolean, default: false, required: false },
ttl: { type: String, required: false },
expiryDate: { type: Date, required: false },
expired: { type: Boolean, default: false, required: false },
applicants: [{ userId: { type: require("mongoose").Schema.Types.ObjectId, ref: "User" } }],
},
{
timestamps: true,
}
);
jobSchema.index({ jobTitle: "text", domain: "text", location: "text" }, { weights: { jobTitle: 3, domain: 2, location: 1 } });
Query Function:
module.exports.getJobs = async (filters, searchText, pageNo, isAuth) => {
try {
if (!filters["expired"]) filters["expired"] = false;
if (!searchText) searchText = null;
return await Job.aggregate([
// { $match: { $or: [filters, { $text: { $search: "Kolkata" } }] } },
{ $match: { $text: { $search: "Kolkata" } } },
{
$facet: {
metadata: [{ $count: "total" }, { $addFields: { page: pageNo } }],
data: [{ $skip: pageNo * 30 }, { $limit: 30 }],
},
},
]);
} catch (err) {
console.log(err);
}
};
The exact behavior I want:
If searchText is null, match the filters. Else, just return the documents that match the searchText on the indexed fields. "Kolkata" is to be replaced by searchText.
The problem:
If the given $match are removed from the aggregate above, the query works fine. Response in Postman:
{
"status": "success",
"message": [
{
"metadata": [
{
"total": 1,
"page": 0
}
],
"data": [
{
"_id": "620aa56f5966e4052229232c",
"emailID": "roy.srijan#gmail.com",
"company": "SpaceShift",
"noOfYearsExperience": "4",
"domain": "Angulaar, React",
"location": "Kolkata",
"jobCreationStatus": "job",
"isActive": true,
"ttl": "2 week",
"expired": false,
"createdAt": "2022-02-14T18:54:39.275Z",
"updatedAt": "2022-02-14T18:54:39.275Z",
"__v": 0,
"jobTitle": "Frontend Developer"
}
]
}
]
}
Using { $match: { $text: { $search: "Kolkata" } } } returns:
{
"status": "success",
"message": [
{
"metadata": [],
"data": []
}
]
}
Using { $match: { $or: [filters, { $text: { $search: "Kolkata" } }] } } returns:
MongoServerError: error processing query: ns=job-database.jobsTree: $or
expired $eq false
TEXT : query=Kolkata, language=english, caseSensitive=0, diacriticSensitive=0, tag=NULL
Sort: {}
Proj: {}
Collation: { locale: "simple" }
planner returned error :: caused by :: Failed to produce a solution for TEXT under OR - other non-TEXT clauses under OR have to be indexed as well.
at MessageStream.messageHandler (/home/deep/Personal/job-qna/node_modules/mongoose/node_modules/mongodb/lib/cmap/connection.js:467:30)
at MessageStream.emit (events.js:375:28)
at processIncomingData (/home/deep/Personal/job-qna/node_modules/mongoose/node_modules/mongodb/lib/cmap/message_stream.js:108:16)
at MessageStream._write (/home/deep/Personal/job-qna/node_modules/mongoose/node_modules/mongodb/lib/cmap/message_stream.js:28:9)
at writeOrBuffer (internal/streams/writable.js:358:12)
at MessageStream.Writable.write (internal/streams/writable.js:303:10)
at TLSSocket.ondata (internal/streams/readable.js:726:22)
at TLSSocket.emit (events.js:375:28)
at addChunk (internal/streams/readable.js:290:12)
at readableAddChunk (internal/streams/readable.js:265:9) {
ok: 0,
code: 291,
codeName: 'NoQueryExecutionPlans',
'$clusterTime': {
clusterTime: new Timestamp({ t: 1645314629, i: 1 }),
signature: {
hash: new Binary(Buffer.from("0fa1bccca48bef06c203ef8c5a16857f5cdf16af", "hex"), 0),
keyId: new Long("7035651653462130689")
}
},
operationTime: new Timestamp({ t: 1645314629, i: 1 })
}

How to find all voted user against each debate in mongoose

I have a debate collection, which holds all the debates and another collection holds the votes against each debate. So I wanted to retrieve all the debates with a new user flag (isVoted) if I found any user in the vote collection against each debate.
Vote model:
var voteSchema = new Schema({
user: { type: Schema.Types.ObjectId, required: true, ref: 'User' }, // One who votes
debate: { type: Schema.Types.ObjectId, required: true, ref: 'Debate' }
}, { timestamps: true });
Debate Model:
var debateSchema = new Schema({
category: { type: Schema.Types.ObjectId, required: true, ref: 'Category' },
question: { type: String, required: true },
Votes: { type: Number, default: 0 },
}, { timestamps: true });
Query
DebateData.aggregate([
{
$match: query
},
{
$sort : { createdAt : -1 }
},
{
$lookup: {
from: "votes", // must be the PHYSICAL name of the collection
localField: "_id",
foreignField: "debate",
as: "votes"
}
},
{
$addFields: {
'isVoted': {
$cond: { if: { $eq: [ '$votes.user', ObjectId(req.query.userId) ] }, then: 'true', else: 'false' }
}
}
},
{
$project: {
'_id': 1,
'question': 1,
'isVoted': 1,
'createdAt': 1
}
},
]).then(result => {
res.status(200).json({ success: true, status: 200, message: 'Debate videos', data: result});
}).catch(err => {
res.status(500).json({ success: false, status: 500, message: err.message })
});
Expected output:
{
"data": [
{
"_id": "60e81f8299a4809658290d80",
"votes": 10,
"category": [
{
"name": "Hockey"
}
],
"question": "What is football?",
"isVoted": true,
"createdAt": "2021-07-09T10:05:54.498Z"
},
{
"_id": "60e438f1194949add0cc2074",
"votes": 12,
"category": [
{
"name": "Cricket"
}
],
"question": "What is football?",
"isVoted": false,
"createdAt": "2021-07-06T11:05:21.654Z"
}
]
}
Current output:
{
"data": [
{
"_id": "60e81f8299a4809658290d80",
"votes": 10,
"category": [
{
"name": "Hockey"
}
],
"question": "What is football?",
"createdAt": "2021-07-09T10:05:54.498Z"
},
{
"_id": "60e438f1194949add0cc2074",
"votes": 12,
"category": [
{
"name": "Cricket"
}
],
"question": "What is football?",
"createdAt": "2021-07-06T11:05:21.654Z"
}
]
}
Vote Data:
{
data: [
{
"user": "69881f8299a480965829ytr267",
"debate": "60e81f8299a4809658290d80"
}
]
}

MongoDB: How to aggregate and $group then filter specific date

Employee Schema
const employeeSchema = new mongoose.Schema(
{
name: {
type: String,
required: true,
trim: true,
},
email: {
type: String,
unique: true,
required: true,
trim: true,
lowercase: true,
validate(value) {
if (!validator.isEmail(value)) {
throw new Error('Email is invalid');
}
},
},
password: {
type: String,
required: true,
trim: true,
minLength: 6,
validate(value) {
if (value.toLowerCase().includes('password')) {
throw new Error("Password can not contain a word 'password'.");
}
},
},
birthdate: {
type: Date,
required: true,
},
cellphone: {
type: String,
required: true,
trim: true,
},
gender: {
type: String,
enum: ['남성', '여성'],
required: true,
},
hourly_wage: {
type: Number,
trim: true,
default: 0,
},
timeClocks: [
{
type: new mongoose.Schema({
start_time: {
type: Date,
required: true,
},
end_time: {
type: Date,
},
wage: {
type: Number,
required: true,
},
total: {
type: Number,
},
totalWorkTime: {
type: Number
}
}),
},
],
role: {
type: String,
enum: ['staff'],
default: 'staff',
},
stores: [
{
location: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'Location',
},
},
],
status: {
//현재 재직상태
type: String,
enum: ['재직자', '퇴직자'],
default: '재직자',
},
tokens: [
{
token: {
type: String,
required: true,
},
},
],
},
{
timestamps: true,
}
);
What I have done so far
const employees = shifts.map((d) => d.owner._id);
//timeclock
const temp = await Employee.aggregate([
{
$match: {
_id: { $in: employees },
},
},
{
$sort: { 'timeClocks.start_time': 1 },
},
{
$unwind: { path: '$timeClocks', preserveNullAndEmptyArrays: true },
},
{
$group: {
_id: '$_id',
name: { $first: '$name' },
timeClock: {
$push: '$timeClocks',
},
},
},
]);
My result
{
"shifts": [
{
"_id": "60e05b188be53900280bcdf2",
"date": "2021-07-09T00:00:00.000Z",
"day": "Fri",
"start": "2021-07-09T09:41:00.000Z",
"end": "2021-07-09T21:42:00.000Z",
"owner": {
"_id": "60cd9a3cb4ddcc00285b0df9",
"name": "Dr. dd"
},
"location": "60cd99b1b4ddcc00285b0df3",
"__v": 0
}
],
"timeClock": [
{
"_id": "60cd9a3cb4ddcc00285b0df9",
"name": "Dr. dd",
"timeClock": [
{
"_id": "60def63d19648a00286f0539",
"start_time": "2021-05-04T02:19:00.000Z",
"end_time": "2021-05-04T14:42:00.000Z",
"wage": 8720,
"total": 107735,
"totalWorkTime": 743
},
{
"_id": "60def63f19648a00286f053d",
"start_time": "2021-05-02T08:12:00.000Z",
"end_time": "2021-05-02T22:24:00.000Z",
"wage": 8720,
"total": 123540,
"totalWorkTime": 852
},
{
"_id": "60def64119648a00286f0541",
"start_time": "2021-05-10T20:14:00.000Z",
"end_time": "2021-05-10T22:17:00.000Z",
"wage": 8720,
"total": 17835,
"totalWorkTime": 123
},
}
]
Expected Result(2021-05-10)
{
"shifts": [
{
"_id": "60e05b188be53900280bcdf2",
"date": "2021-07-09T00:00:00.000Z",
"day": "Fri",
"start": "2021-07-09T09:41:00.000Z",
"end": "2021-07-09T21:42:00.000Z",
"owner": {
"_id": "60cd9a3cb4ddcc00285b0df9",
"name": "Dr. dd"
},
"location": "60cd99b1b4ddcc00285b0df3",
"__v": 0
}
],
"timeClock": [
{
"_id": "60cd9a3cb4ddcc00285b0df9",
"name": "Dr. dd",
"timeClock": {
"_id": "60def64119648a00286f0541",
"start_time": "2021-05-10T20:14:00.000Z",
"end_time": "2021-05-10T22:17:00.000Z",
"wage": 8720,
"total": 17835,
"totalWorkTime": 123
},
}
]
I am receiving the 'date string' example('URL/2021-05-10') via params and trying to query all employees that have the same date timeClocks.
also trying to send back everything I queried without different dates from timeClocks.
How can I filter out non-same dates?
You have string 2021-05-10 now you need a $match stage before your group so you can filter out timeClock. Something like:
{ $match: { 'timeClocks.start_time': new Date('2021-05-10') } }
Modify the match stage to your requirements like maybe add $gte or $lte or something like that.

Sequelize - Return only relationships

I have a problem, I need to return an array just from my flows relationship. How can I get an array with a list of the flows of all companies?
My model and migrations are correct, I just don't know how to make the query return only the flows.
Company Model
module.exports = (sequelize) => {
const company = sequelize.define('company', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
uuid: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4
},
name: {
type: DataTypes.STRING,
allowNull: false
}
})
company.hasMany(sequelize.models.flow, {foreignKey: 'company_id', as: 'flows'})
}
Flow model
module.exports = (sequelize) => {
const flow = sequelize.define('flow', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: DataTypes.INTEGER
},
company_id: {
allowNull: false,
type: DataTypes.INTEGER
},
uuid: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4
},
name: {
type: DataTypes.STRING,
allowNull: false
},
description: {
type: DataTypes.TEXT
}
})
flow.belongsTo(sequelize.models.company, {foreignKey: 'company_id', as: 'company'})
}
Query
const companies = await ORM.models.company
.findAll({
include: [{
model: ORM.models.flow,
as: 'flows'
}]
})
This query is returning like this:
[
{
"id": 1,
"uuid": "f0c1a5e1-c54c-4083-8284-5a9b272e8ba1",
"name": "Company 1",
"created_at": "2021-02-11T05:47:55.830Z",
"updated_at": "2021-02-11T05:47:55.830Z",
"flows": [
{
"id": 1,
"company_id": 1,
"uuid": "768262d2-88b7-4e0f-81e8-30d7253aae65",
"name": "Flow 1",
"description": null,
"created_at": "2021-02-11T05:48:10.211Z",
"updated_at": "2021-02-11T05:48:10.211Z",
"companyId": 1
}
]
},
{
"id": 2,
"uuid": "3dea2541-a505-4f0c-a356-f1a2d449d050",
"name": "Company 1",
"created_at": "2021-02-11T05:48:11.872Z",
"updated_at": "2021-02-11T05:48:11.872Z",
"flows": [
{
"id": 2,
"company_id": 2,
"uuid": "3e66e8e6-3754-41e5-93ca-6e8ed49e2025",
"name": "Flow 2",
"description": null,
"created_at": "2021-02-11T05:48:20.743Z",
"updated_at": "2021-02-11T05:48:20.743Z",
"companyId": 2
}
]
}
]
I need to return like this:
[
{
"id":1,
"company_id":1,
"uuid":"768262d2-88b7-4e0f-81e8-30d7253aae65",
"name":"Flow 1",
"description":null,
"created_at":"2021-02-11T05:48:10.211Z",
"updated_at":"2021-02-11T05:48:10.211Z",
"companyId":1
},
{
"id":2,
"company_id":2,
"uuid":"3e66e8e6-3754-41e5-93ca-6e8ed49e2025",
"name":"Flow 2",
"description":null,
"created_at":"2021-02-11T05:48:20.743Z",
"updated_at":"2021-02-11T05:48:20.743Z",
"companyId":2
}
]
If you just want the flows related data, why to fetch company related data with flows in it? Perhaps, you could only fetch flows data.
const flows = await ORM.models.flow
.findAll({
where: ....,
..........
});
If anyhow, you still want to show the flows for particular companies without showing any attributes of the company model, just do something like this:
const companies = await ORM.models.company
.findAll({
attributes: [], //empty
include: [{
model: ORM.models.flow,
as: 'flows'
}]
});

Collections association with nested in Mongoose

I had a problem with the association of collections.
I spent 2 days and still did not solve the problem, it's new for me.
My models:
// Schema opened cases
const openedSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'user',
required: [true, 'user is required'],
index: true
},
weapon: {
type: Schema.Types.ObjectId,
ref: 'cases.weapons',
required: [true, 'weapon is required'],
index: true
},
sellPrice: {
type: Number,
default: null
},
status: {
type: Number,
default: 0
}
}, {
timestamps: true
});
const opened = mongoose.model('opened', openedSchema);
// list cases
const casesSchema = new Schema({
name: {
type: String,
unique: true,
required: [true, 'name is required']
},
price: {
type: Number,
required: [true, 'price is required']
},
weapons: [ {
weapon: {
type: Schema.Types.ObjectId,
ref: 'weapon',
index: true
}
} ]
}, {
timestamps: false
});
const cases = mongoose.model('cases', casesSchema);
// list weapons
const weaponSchema = new Schema({
name: {
type: String,
unique: true,
required: [true, 'name is required']
},
price: {
type: Number,
required: [true, 'price is required']
},
autoship: {
count: Number,
status: Boolean,
price: Number
}
}, {
timestamps: false
});
const weapon = mongoose.model('weapon', weaponSchema);
That's what documents look like
// cases
{
"_id": {
"$oid": "59653bcfa9ac622e1913e10c"
},
"name": "test case #1",
"price": 256,
"weapons": [
{
"weapon": {
"$oid": "59653bcfa9ac622e1913e10b"
},
"_id": {
"$oid": "59653bcfa9ac622e1913e10d"
}
},
{
"_id": {
"$oid": "59653d3279aeda2fda9fb490"
},
"weapon": {
"$oid": "59653c5d069f562eb0ba4ef3"
}
},
{
"_id": {
"$oid": "59653d38ba04de2fdddc459f"
},
"weapon": {
"$oid": "59653c893a772e2ef7b65a29"
}
}
],
"__v": 0
}
// opened
{
"_id": {
"$oid": "5965d134c8c95972a1a498f5"
},
"updatedAt": {
"$date": "2017-07-12T07:35:16.419Z"
},
"createdAt": {
"$date": "2017-07-12T07:35:16.419Z"
},
"user": {
"$oid": "5965d0d6ea9db872360db98b"
},
"weapon": {
"$oid": "59653bcfa9ac622e1913e10d"
},
"status": 0,
"sellPrice": null,
"__v": 0
}
// weapon
{
"_id": {
"$oid": "59653bcfa9ac622e1913e10b"
},
"name": "AWP | Fever Dream",
"price": 300,
"autoship": {
"status": true,
"price": 167,
"count": 5
},
"__v": 0
}
I need to get a list of open cases with weapons data.
opened -> cases -> weapon
So, I do this:
opened.find()
.populate('cases.weapons')
.then(_opened => {
console.log(_opened);
})
.catch(err => {
logger.error(err);
});
But populate does not work.
Unless I am mistaken, there is no relationship between openedSchema and casesSchema.
It is not opened -> cases -> weapon but opened -> weapon as openedSchema has no field called cases -- which means cases will never be populated.
Based on your schema definition, it should be opened.find().populate('weapon').

Resources