mongodb find from array and then from object id by refrence - mongodb

I want to seach order list with product division id. means i can provide division id and get order list of that perticular division.
I'm trying this query, but it return 0 elements
db.getCollection('orders').find({$or:
[{'orderlist':{"$elemMatch":{'product_id.division_id':ObjectId("5f5b1511a859865ac9b0efe5")}}}]
})
My Order Schema
const orderSchema = new mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
orderlist: [{
product_id: { type: mongoose.Schema.Types.ObjectId, ref: 'Product', required: [true, "Product Id is Required"] },
quantity: { type: Number, required: [true, "Product Quantity is Required"] },
packing_type: { type: String, default: null }
}]
});
My Product Schema
const productSchema = new mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
division_id: { type: mongoose.Schema.Types.ObjectId, ref: 'Division', required: [true, "Product Division Id is Required"] },
name: { type: String, required: [true, "Product Name is Required"] },
price: { type: Number, required: [true, "Product Price is Required"] },
description: { type: String, required: [true, "Product Description is Required"] },
technical_detail: { type: String, default: null },
packing: { type: String, default: null },
packing_type: { type: String, default: null }
});```

To filter query calls with a ref schema first of all you need to lookup it from the server. In your case, it is a mongoose object id not an object of elements.
To merge schemas I recommend using aggregation.$lookup(aggregation)
db.getCollection('orders').aggregate([
{
$lookup: {
from: 'product',
localField: 'orderlist.product_id',
foreignField: '_id',
as: 'products',
},
},
])

Related

Id is created for every nested objects in documents of a collection in mongodb via mongoose

I have a user schema. While saving document, for every nested object (quizHistory,record & responses) in document, mongoose add _id field automatically. For ref- quizHistory path
const userSchema = new Schema({
firstName: { type: String, required: true ,trim:true},
lastName:{ type: String, required: true ,trim:true},
email: { type: String, unique: true, required: true },
isUser: { type: Boolean, default: true },
password: String,
quizHistory: [{
quizId: { type: Schema.Types.ObjectId, ref: 'Quiz' },
record: [{
recordId:{ type: Number},
startTime: { type: Date },
responses: [{
quesId: { type: Schema.Types.ObjectId, ref: 'Question' },
answers: [Number]
}],
score: Number
}],
avgScore: Number
}]
})
Mongoose create virtual id by default(guide id).
Add this line to your schema.
_id : {id:false}

Is it possible to have two types of objects in an array of mongoose schema

I am building an e-commerce application and this is my orders schema.
const mongoose = require("mongoose");
const orderSchema = new mongoose.Schema({
buyer: {
type: mongoose.Schema.Types.ObjectId,
ref: "buyer",
required: true
},
items: [{
item: {
type: mongoose.Schema.Types.ObjectId,
ref: "item",
},
quantity: {
type: Number,
default: 1
}}
],
seller: {
type: mongoose.Schema.Types.ObjectId,
ref: "seller",
required: true
},
location: {
type: {
type: "String",
enum:['Point']
},
coordinates: {
type: [Number],
index: '2dsphere'
}
},
sendAt:{
type: Date,
default: Date.now
}
});
const orderModel = mongoose.model("orders", orderSchema);
module.exports = orderModel;
I want to have an array having item-reference-id and quantity.
But with the above schema when i enter data, each item is acting as an another sub-document and having _id. Query response image.
I have found solution:
order: [
{
_id: false,
item: {
type: mongoose.Schema.Types.ObjectId,
ref: "items",
required: true,
},
quantity: { type: Number },
},
],
_id: false will stop the subdocument from creating another id for the subdocument.

Associate one schema with another

I have my user schema:
const userSchema = new Schema({
name: { type: String, required: true },
email: { type: String, required: true },
password: { type: String, required: true },
date: { type: Date, default: Date.now },
active: { type: Boolean, default: false }
});
I want to create a leave status schema. Data will be given by only one user about all leave status. I want to associate each one of the leave status to there respective user schema id. I tried leave status schema as the following:
const leaveSchema = new Schema({
leave: [
{
email: { type: String, required: true },
month: { type: String, required: true },
year: { type: Number, required: true },
earnedleave: { type: Number },
sickleave: { type: Number },
festivalleave: { type: Number },
compoff: { type: Number }
}
]
});
How can i associate my emailid with userschema. Can it be possible? If so, how can i tweak it?
We don't need to associate the schema to get leave based on user, You can use aggregation for that,
db.user.aggregate([
...
{$lookup: {from: "leave", localField: "email", foreignField: "leave.email", as: "leaves"}},
...
]);
Still, If you like to associate two collection, You have to use ref using ObjectId
const leaveSchema = new Schema({
leave: [
{
user: { type: Schema.Types.ObjectId, ref: 'user' }, //Your model name as reference
email: { type: String, required: true },
month: { type: String, required: true },
year: { type: Number, required: true },
earnedleave: { type: Number },
sickleave: { type: Number },
festivalleave: { type: Number },
compoff: { type: Number }
}
]
});

$lookup work in MongoDB but doenst work with mongoose

I have two Documents:
Category = new Schema({
storeKey: { type: String, required: true },
cod: { type: String, required: true },
name: { type: String, required: true },
visible: { type: Boolean }
},
{
timestamps: {
createdAt: "created",
updatedAt: "updated"
}
}
);
and:
Product = new Schema({
name: { type: String, required: true },
cod: String,
storeKey: { type: String, required: true },
categoryId: String,
description: { type: String, required: true },
price: { type: Number, required: true },
stockQuantity: { type: Number, required: true },
avatar: String,
visible: Boolean
}, {
timestamps: true
});
Query on server whith mongoose to locate products with the aggregate category
Product.aggregate([
{
$lookup: {
from: "Category",
localField: "categoryId",
foreignField: "_id",
as: "category"
}
}]
).exec((error, done) => {
if (error) res.status(500).send({
message: langs[req.query.lang],
error
});
res.status(200).send(done);
});
query on local terminal
db.Product.aggregate(
[{
$lookup: {
localField: "categoryId",
from: "Category",
foreignField: "_id",
as: "category"
}
}])
In the terminal, $lookup works correctly. With mongoose, it brings duplicate records and does not bring existing categories. What is wrong?
#Anthony Winzlet was correct, should be categories (in the pural) would have to leave categories (in the pural) and not category, but also, i had not defined the categoryId field as being an ObjectId in the Product Schema, so it was comparing string with ObjectId. In the tests in the terminal I had saved the server return, which returns the _id fields as strings. Now it's working.Thanks!
const ProductSchema = new Schema({
name: { type: String, required: true },
cod: String,
storeKey: { type: String, required: true },
categoryId: { type: Schema.Types.ObjectId, ref: 'categories' },
description: { type: String, required: true },
price: { type: Number, required: true },
stockQuantity: { type: Number, required: true },
avatar: String,
visible: Boolean
}, {
timestamps: true
});

Need help to make mongo $lookup query

This is my table structure
Group -> _id,name,description,type
GroupMembers -> _id, group(FK),status,Isinvited, user_id(Fk)
User -> _id,name,email,role
Need :- I want to get groups with its active members (status = true) aslo need the name of users from User collections
Current Code :-
Group.aggregate([
{
$lookup: {
from: "groupmembers",
localField: "_id",
foreignField: "group",
as: "membersList"
}
},
{
$lookup : {
from: "users",
localField: "membersList.user",
foreignField: "_id",
as: "userss"
}
},
{
$match:{"_id" : mongoose.Types.ObjectId("5abe70eb7ede1b695e9342d6")}
},
{
$project:{"_id":1,"name":"$name","member":{"membersList":"$membersList","userss":"$userss"}}
}
])
Getting the response but not in well manners go like ->
[
{
"_id": "5abe70eb7ede1b695e9342d6",
"name": "Welcome To Hobnobbin",
"member": {
"membersList":["Got memebrsLiset from GroupMembers"],
"userss": ["Got users from groupMembers FK "]
}
}
]
How can I get it like
[
{
"_id": "5abe70eb7ede1b695e9342d6",
"name": "Welcome To Hobnobbin",
"member": {
"membersList":["Got memebrsLiset from GroupMembers",user: "Userobject here"],
}
}
]
Collections : ->
var GroupSchema = new Schema({
name: {
type: String,
required: 'Please fill Group name',
trim: true
},
photo:{
type:String
},
type: {
type: [{
type: String,
enum: ['child', 'adult']
}],
required: 'Please select at least one type'
},
description:{
type:String,
default:''
},
pinnedTweet:{
type:String,
default:''
},
/*members: [{
type: Schema.ObjectId,
ref: 'User'
}],*/
jointype: {
type: String,
enum: ['openToJoin', 'openToRequest', 'inviteOnly'],
default: 'openToJoin',
required: 'Please select at least one behavious of group'
},
created: {
type: Date,
default: Date.now
},
user: {
type: Schema.ObjectId,
ref: 'User'
},
createByHobnob: {
type: Boolean,
default: false
},
isWelcomeGroup: {
type: Boolean,
default: false
},
allowPrivateChat: {
type: Boolean,
default: false
}
});
var GroupMemberSchema = new Schema({
user : {
type: Schema.ObjectId,
ref: 'User'
},
group : {
type: Schema.ObjectId,
ref: 'Group'
},
role: {
type: String,
enum: ['member', 'ban', 'moderator', 'admin'],
default: 'member',
required: 'Please select at least one role'
},
is_active: {
type: Boolean,
default: false
},
is_invited: {
type: Boolean,
default: false
},
created: {
type: Date,
default: Date.now
},
allowChat: {
type: Boolean,
default: true
}
});
var UserSchema = new Schema({
firstName: {
type: String,
trim: true,
default: ''
},
lastName: {
type: String,
trim: true,
default: ''
},
displayName: {
type: String,
trim: true
},
email: {
type: String,
unique: true,
lowercase: true,
trim: true,
default: '',
validate: [validateLocalStrategyEmail, 'Please fill a valid email address']
}
});