Is it possible using Node.js, Express and Mongoose for MongoDB to have a link to a sub-document.
He is one of my document containing platforms sub-Documents:
// A product description
{
"name": "My product",
"operator": "5288c2bdb0269e1c85000003",
"_id": "528909ff1225faa801000004",
"platforms": [
{
"name": "Platform 1",
"_id": "528909ff1225faa801000007"
},
{
"name": "Platform 2",
"_id": "528909ff1225faa801000006"
},
{
"name": "Platform 3",
"_id": "528909ff1225faa801000005"
}
]
}
I also have a Variable document which have sub-document related to platforms:
// Variable description
{
"name": "My variable",
"values": [
{
"platform": "528909ff1225faa801000007",
"values": "value 1"
},
{
"platform": "528909ff1225faa801000006",
"values": "value 2"
},
{
"platform": "528909ff1225faa801000005",
"values": "value 3"
}
]
}
In Mongoose, is it possible to have a schema reflecting it ?
You can either do this:
ProductSchema = new Schema({
name: {type: String},
operator: {type: Schema.Types.ObjectId},
platforms: [{
name: {type: String},
}],
})
or this:
ProductSchema = new Schema({
name: {type: String},
operator: {type: Schema.Types.ObjectId},
platforms: [PlatformSchema],
})
Related
one collection is carts
[{
"_id": {
"$oid": "633a71cd3a9706174ef57f41"
},
"ProductName": "Natural Blue Sapphire",
"Quantity": 1,
"Price": 20100
},
{
"_id": {
"$oid": "633ae81727e12df99604d9d7"
},
"ProductName": "Natural Blue Sapphire",
"Quantity": 1,
"Price": 20100
}]
`
other collection is orderhistories
`
[{
"_id": {
"$oid": "62f399fc5001311d30680e81"
},
"Address": {
"firstName": "Ronit"
},
"MemberId": {
"$oid": "62e50e29adb262e58ad1f920"
},
"cartItems": [
{
"$oid": "62f399985001311d30680e7e"
}
],
"status": "Delivered"
},{
"_id": {
"$oid": "62ff2b0f0fe010c6e4b0a05d"
},
"Address": {
"firstName": "Ronit"
},
"MemberId": {
"$oid": "62e50e29adb262e58ad1f920"
},
"cartItems": [
{
"$oid": "62f399985001311d30680e7e"
}
],
"status": "Created"
}
`
i want to get cart list using cartItems doc in orderhistories collection
and i am doing this
`
const order = await OrderHistory.find({$or:[{MemberId:Id}] }).sort({"createdAt": -1}).populate('offerCode MemberId cartItems.cart')
res.json(order)
`
my order history model is
`
const orderHistory = new mongoose.Schema({
Address:{
type: mongoose.SchemaTypes.Mixed,
},
MemberId:{
type: mongoose.Schema.Types.ObjectId,
ref:'Member_detail'
},
cartItems:[{
cart:{
type: mongoose.Schema.Types.ObjectId,
ref:'cart'
}
}],
status:{
type:String,
default:"Created"
},
}, {
timestamps: true
})
`
and my cart model schima is
`
const cart_schema = new mongoose.Schema({
Member_Id:{
type: mongoose.Schema.Types.ObjectId,
ref:'Member_detail'
},
ProductId:{
type: mongoose.Schema.Types.ObjectId,
ref:'Product_details'
},
ProductName: {
type: String,
},
status:{type:Number ,
default:1} // 1 = Active 0 = inactive i.e order placed
}, {
timestamps: true
})
`
I need data from carts collection when find ordershistory collection. in orderhistry collection have carts doc. so I need data all data according to id in carts doc
Expected Output
[
{
"_id": "636e73fe398888caca60da16",
"cartItems": [
{
"_id": "6379d76e6274ddb0910f72bc",
"ProductName": "Natural Blue Sapphire",
"Price": 1000,
}
],
"total": 1802.5,
}]
I am making a node.js application where I am trying to query an array using mongoose and I am being returned the complete unfiltered document.
The collection stores a single document with the following Data (This is also the data that I am receiving after executing the query):
{
"_id": {
"$oid": "60c0900f619f89f6943efbfd"
},
"milestones": [{
"id": "1",
"name": "5 Friends",
"description": "refer 5 friends to get 100 GroCash!",
"isActive": true,
"reward": 100,
"condition": 5
}, {
"id": "2",
"name": "7 Friends",
"description": "refer 7 friends to get 100 GroCash!",
"isActive": true,
"reward": 150,
"condition": 7
}, {
"id": "3",
"name": "5 Friends",
"description": "refer 5 friends to get 100 GroCash!",
"isActive": true,
"reward": 550,
"condition": 5
}],
"newUserReward": 50,
"refreeReward": 50
}
The query that I am running is : incentiveModel.find({'milestones.isActive':true,'milestones.condition':5})
I am expecting it to return me the following data :
{
"_id": {
"$oid": "60c0900f619f89f6943efbfd"
},
"milestones": [{
"id": "1",
"name": "5 Friends",
"description": "refer 5 friends to get 100 GroCash!",
"isActive": true,
"reward": 100,
"condition": 5
}, {
"id": "3",
"name": "5 Friends",
"description": "refer 5 friends to get 100 GroCash!",
"isActive": true,
"reward": 550,
"condition": 5
}],
"newUserReward": 50,
"refreeReward": 50
}
I have tried $project but still no help.
The mongoose schema is :
const milestone = new Schema({
id:{
type:String,
required:true,
default:mongoose.Types.ObjectId()
},
name:{
type:String,
required:true,
default:''
},
description:{
type:String,
required:true,
default:''
},
isActive:{
type:Boolean,
required:true,
default:false
},
condition:{
type:Number,
required:true,
default:null
},
reward:{
type:Number,
required:true,
default:0
}
})
export const incentiveScema = new Schema({
milestones:{
type:[milestone]
},
newUserReward:{
type:Number,
default:0
},
refreeReward:{
type:Number,
default:0
}
})
Thanks in advance!
await incentiveModel.aggregate([
{
$unwind:'$milestones'
}
{
$match:{
$and:[{'milestones.isActive':true},{'milestones.condition':5}]
}
])
refer to this example below..
https://mongoplayground.net/p/Xrrby8yN0IS
Probably you could use aggregate with $addFields on which you can filter out the data. Below is the query for the same. for more reference please go through the this link.
check the sample example
db.collection.aggregate([
{
$addFields: {
"milestones": {
$filter: {
input: "$milestones",
as: "milestones",
cond: {
$and: [
{
$eq: [
"$$milestones.isActive",
true
]
},
{
$eq: [
"$$milestones.condition",
5
]
}
]
}
}
}
}
}
])
I need to join user collections two times as same user will post product and purchased user details as sub document.
Product Schema:
{
product_title: String,
product_desc: String,
Product_purchased:[
{
userid: mongoose.Schema.ObjectId,
purchased_date: Date
}]
posteduserId: mongoose.Schema.ObjectId
}
Users Schema:
{
_id: userId,
name: String,
Pic: String
}
Example document:
[
{
"product_title":"title",
"product_desc":"desc",
"Product_purchased":[
{
"userid":"5d4hvh7duc7c7c8d9scbe",
"name":"name",
"Pic":"url",
"purchased_date":"Date"
},
{
"userid":"5d4hvh7duc7c7c8d9scbe",
"name":"name",
"Pic":"url",
"puchased_date":"Date"
}
],
"posteduserId": "5d4hvh7duc7c7c8d9scbe",
"userid": "5d4hvh7duc7c7c8d9scbe",
"name": "name",
"pic": "url",
}
]
Join same user table with posted userid and subarray of purchased userIds.
Please help me how to crack this one, Thanks in advance.
First you need to fix your Product schema like this to include the ref field:
const mongoose = require("mongoose");
const ProductSchema = new mongoose.Schema({
product_title: String,
product_desc: String,
Product_purchased: [
{
userid: {
type: mongoose.Schema.ObjectId,
ref: "User"
},
purchased_date: Date
}
],
posteduserId: {
type: mongoose.Schema.ObjectId,
ref: "User"
}
});
module.exports = mongoose.model("Product", ProductSchema);
I setup user model like this:
const mongoose = require("mongoose");
const UserSchema = new mongoose.Schema({
name: String,
Pic: String
});
module.exports = mongoose.model("User", UserSchema);
The ref User value must match the model name User in the user model.
Then you need to populate two times like this:
router.get("/products", async (req, res) => {
const result = await Product.find({})
.populate("Product_purchased.userid")
.populate("posteduserId");
res.send(result);
});
Let's say you have this 3 users:
{
"_id": "5e133deb71e32b6a68478ab4",
"name": "user1 name",
"Pic": "user1 pic",
"__v": 0
},
{
"_id": "5e133df871e32b6a68478ab5",
"name": "user2 name",
"Pic": "user2 pic",
"__v": 0
},
{
"_id": "5e133e0271e32b6a68478ab6",
"name": "user3 name",
"Pic": "user3 pic",
"__v": 0
}
And this product:
{
"_id": "5e133e9271e32b6a68478ab8",
"product_title": "product1 title",
"product_desc": "product1 description",
"Product_purchased": [
{
"purchased_date": "2020-01-06T14:02:14.029Z",
"_id": "5e133e9271e32b6a68478aba",
"userid": "5e133df871e32b6a68478ab5"
},
{
"purchased_date": "2020-01-06T14:02:14.029Z",
"_id": "5e133e9271e32b6a68478ab9",
"userid": "5e133e0271e32b6a68478ab6"
}
],
"posteduserId": "5e133deb71e32b6a68478ab4",
"__v": 0
}
The result will be:
[
{
"_id": "5e133e9271e32b6a68478ab8",
"product_title": "product1 title",
"product_desc": "product1 description",
"Product_purchased": [
{
"purchased_date": "2020-01-06T14:02:14.029Z",
"_id": "5e133e9271e32b6a68478aba",
"userid": {
"_id": "5e133df871e32b6a68478ab5",
"name": "user2 name",
"Pic": "user2 pic",
"__v": 0
}
},
{
"purchased_date": "2020-01-06T14:02:14.029Z",
"_id": "5e133e9271e32b6a68478ab9",
"userid": {
"_id": "5e133e0271e32b6a68478ab6",
"name": "user3 name",
"Pic": "user3 pic",
"__v": 0
}
}
],
"posteduserId": {
"_id": "5e133deb71e32b6a68478ab4",
"name": "user1 name",
"Pic": "user1 pic",
"__v": 0
},
"__v": 0
}
]
I have an endpoint which gives me a list of all Profiles available, now I have a Post Schema & Profile Schema, I want to add a list of posts that specific users have made to my result
Code present in endpoint
const profiles = await Profile.find()
.populate('user', [
'name',
'avatar'
])
Profile Schema
const ProfileSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
},
post: [],
........
Post Schema
const PostSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'user'
},
text: {
type: String,
required: true
},
........
Response
[
{
"social": {
"youtube": "https://youtube.com/.",
"twitter": "https://twitter.com/.",
"facebook": "https://fb.com/."
},
"post": [], //This should populate
"skills": [
"HTML",
"CSS",
"PHP",
"Ruby"
],
"_id": "5ced6cb9e3f7485ee2cb0445",
"user": {
"_id": "5ced02551b60fe20afc72a32",
"name": "John abc",
"avatar": "//www.gravatar.com/avatar/1f9d9a9efc2f523b2f09629444632b5c?s=200&r=pg&d=mm"
},
"status": "Developer",
"experience": [
{
"current": true,
"_id": "5ceebb30bb0c667b85a94f97",
"from": "2010-08-09T18:30:00.000Z",
"description": "lorem ipasum"
}
],
"date": "2019-05-28T17:15:37.755Z",
"__v": 30,
"bio": "I am dev",
"education": [
{
"current": false,
"_id": "5cf0c1dc6b8dc33cd68be560",
"degree": "BE",
"from": "2005-07-09T18:30:00.000Z",
"to": "2010-03-03T18:30:00.000Z",
"description": "Got BE"
}
]
}
]
Expected output
[
{
"social": {
"youtube": "https://youtube.com/.",
"twitter": "https://twitter.com/.",
"facebook": "https://fb.com/."
},
"post": [
{_id:98as98djakjbkasd,
text:"This is post by xyz user"
},
{_id:234oijaoijd,
text:"This is another post by xyz user"
}
]
"skills": [
"HTML",
"CSS",
"PHP",
"Ruby"
],
"_id": "5ced6cb9e3f7485ee2cb0445",
"user": {
"_id": "5ced02551b60fe20afc72a32",
"name": "John abc",
"avatar": "//www.gravatar.com/avatar/1f9d9a9efc2f523b2f09629444632b5c?s=200&r=pg&d=mm"
},
.....
I want to populate posts done by the same user, what changes are needed to be done in endpoint code.
I am new to mongoose, upon searching for solutions I found aggregate could be useful but it cannot be used like .find().aggregate([...])
Trying to join in MongoDB would defeat the purpose of using MongoDB. As we first think about our use case then decide database and schema. You could however use DBref and write your own application code.
Another thing you can alter your schema into a single collection and use embedded document
It's always a suggestion of MongoDB that avoid join in our query!
This question already has answers here:
Querying after populate in Mongoose
(6 answers)
Closed 5 years ago.
I need to filter my business document according to a type of service.
var BusinessSchema = Schema({
name: String,
slug: String,
service: [{type: Schema.ObjectId, ref: 'Service'}],
owner: {type: Schema.ObjectId, ref: 'User'}
});
module.exports = mongoose.model('Business', BusinessSchema);
And Schema service is:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ServiceSchema = Schema({
name: String,
});
module.exports = mongoose.model('Service', ServiceSchema);
Of this array of businesses would only need those that have within its services the "Service A" for example.
"business": [
{
"_id": "594957df4e195d2500324726",
"owner": "59482e80d4df7208503154b8",
"slug": "Almacene2s",
"name": "Almacene2s",
"__v": 0,
"service": [
{
"_id": "594ab160778ae82c44af3a78",
"name": "Service C",
"__v": 0
},
{
"_id": "594ab1be778ae82c44af3a7a",
"name": "Service D",
"__v": 0
}
],
},
{
"_id": "5948483e6bcc1f2788b09145",
"owner": "59482e80d4df7208503154b8",
"slug": "guaranda-2",
"name": "Guaranda Fig",
"service": [
{
"_id": "594ab160778ae82c44af3a78",
"name": "Service A",
"__v": 0
},
{
"_id": "594ab1be778ae82c44af3a7a",
"name": "Service B",
"__v": 0
}
],
}
]
In this case the result I want to get is:
{
"_id": "5948483e6bcc1f2788b09145",
"owner": "59482e80d4df7208503154b8",
"slug": "guaranda-2",
"name": "Guaranda Fig",
"service": [
{
"_id": "594ab160778ae82c44af3a78",
"name": "Service A",
"__v": 0
},
{
"_id": "594ab1be778ae82c44af3a7a",
"name": "Service B",
"__v": 0
}
],
}
It is very important for me to be able to carry out this search, because the system will allow the user to choose as a filter the business that has the desired service.
It's my first project on nodejs + mongodb and I would like your help before continuing on. Thank you very much
Using $lookup, here's what you can achieve:
Service.aggregate([
{
$match: {
"name": "Service A"
}
},
{
$lookup: {
from: "business",
localField: "_id",
foreignField: "service",
as: "businesses"
}
}
], function(err, result) {
console.log(result);
});
In this aggregation pipeline, you first match and find service documents with name "Service A". Then lookup in service array of business documents for matching ones and place them in businesses field. The result will look like this:
{
"_id" : "594af96883ab76db8ecd021b",
"name" : "Service A",
"businesses" : [
{
"_id" : "594af9a683ab76db8ecd0225",
"slug" : "Almacene2s",
"owner" : "59482e80d4df7208503154b8",
"name" : "Almacene2s",
"service" : [
"594af96883ab76db8ecd021b",
"594af96883ab76db8ecd021d"
]
}
]
}