I'm trying to obtain the objects inside the reviews array by matching the fb_id's that I'm passing. I do not seem to get them to work. This is my actual document in the DB
{
"_id": {
"$oid": "5841d18187dcc74805887a6a"
},
"product_id": "583ae172231f5ec01db5727e",
"category": "Smartphones",
"reviews": [
{
"fb_id": "111",
"name": "name1",
"user_img": "imgurl1",
"title": "asdakj",
"description": "jnkjnkj",
"rating": 5,
"_id": {
"$oid": "5841d18187dcc74805887a6b"
}
},
{
"fb_id": "222",
"name": "name2",
"user_img": "imgurl2",
"title": "dadad",
"description": "asdasdad",
"rating": 3,
"_id": {
"$oid": "5841d1d0cbdf333411530ebd"
}
},
{
"fb_id": "333",
"name": "name3",
"user_img": "img url3",
"title": "asdad",
"description": "asdads",
"rating": 5,
"_id": {
"$oid": "5841d4c2174270f807084721"
}
},
{
"fb_id": "444",
"name": "name4",
"user_img": "imgurl4",
"title": "adasd",
"description": "kjnkj",
"rating": 1,
"_id": {
"$oid": "5841d569eae1b6600ea1ca92"
}
}
],
"__v": 0
}
I will be sending an array of fb_id's to mongoose and want the results only for the objects inside the array that has the fb_id's.
This is my query now:
Review.find({ product_id: '583ae172231f5ec01db5727e' }, { 'reviews.$.fb_id': { $in: <array of fb_id> } }, function(err, results) {
if (err) {
throw err;
};
console.log(results)
});
But it gives me this error :
MongoError: Unsupported projection option: reviews.$.fb_id: { $in: [ 111.0 ] }
EDIT: After a small query, now I am to get some results. But the result has only the first object that match from the fb_id's and not all.
Please tell me how I can achieve this.
You can use this for reference.
your code would be something like this:
Review.find({
product_id: '583ae172231f5ec01db5727e'
},
{
reviews: {
$elemMatch: {
fb_id: {
$in: <array of fb_id>
}
}
}
},
{
_id: 0,
'reviews.$': 1
}
, function(err, results) {
if (err) {
throw err;
};
console.log(results)
});
Related
In my client I have a form that is sent and stored in Mongo. Made an aggregation to get the name of the people that selected a same place, date and time. Now I would like to create a Mongo document containing all matches as collections so whenever there is a match in place, date and time of people you can get it in a collection. This is what I have so far:
router.get('/match', async (req, res) => {
const matchs = await Forms.aggregate([
{
$group: {
_id: { Date: "$date", Time: "$time", Place: "$place" },
Data: { $addToSet: {Name: "$firstName", Surname:"$surname"}},
count: { $sum: 1 }
}
},
{
$match: {
count: { $gte: 2}
}
},
]);
res.json(matchs)
});
This is the result that I would like to store in Mongo:
{
"_id": {
"Date": "2022-04-20",
"Time": "15:00",
"Place": "Mall"
},
"Data": [
{
"Name": "Carl",
"Surname": "Man"
},
{
"Name": "Christian",
"Surname": "Max"
}
],
"count": 2
}
{
"_id": {
"Date": "2022-04-20",
"Time": "13:00",
"Place": "Restaurant"
},
"Data": [
{
"Name": "Felix",
"Surname": "Sad"
},
{
"Name": "Liu",
"Surname": "Lam"
}
],
"count": 2
}
You can use $out as the last stage in your pipeline. In the following example, matching_collection will contain the result of your pipeline.
{ $out : "matching_collection" }
https://www.mongodb.com/docs/v4.2/reference/operator/aggregation/out/
You can also check $merge, it could be helpful as well.
I have visitors array. Based on length I want to fetch first 40(highest visted) videos. Is there any query in mongoose for this?
"videos": [],
"description": "Runs for indai",
"status": 1,
"_id": "5e68ee512d3fe53a4426fea5",
"likes": [],
"visited": [{
"_id": "5e690d28797f5b05e066104d",
"user": "::1"
},
{
"_id": "5e690d14797f5b05e066104c",
"user": "::1"
},
{
"_id": "5e690cf7797f5b05e066104b",
"user": "::1"
}],
"comments": [],
"embed": "https://wwdalkfa.com/idaa/46221",
"category": "Mathrubhumi",
"title": "Bdis idnc - Aria.",
"link": "https://www.mdaoa.com/video/46221/dafa",
"image": "https://www.mdaoa.com/media/videos/dstmb1/46221/1b.jpg",
"keywords": "adjal","DAfa",
"__v": 0
controller
exports.getTrendingVideos = async (req, res) => {
try {
const videos = await Video.find().limit(40);
res.send(videos);
} catch (error) {}
};
First, get the length of the array and then sort it, You can do it like this
const videos = await Video.aggregate([
{ $project: { visitedCount: { $size: '$visited' } } },
{ $sort: { $visitedCount: -1 } },
]).limit(40);
I'm trying to delete a subdocuments in array with Mongoose.
My datas :
{
"_id": {
"$oid": "5d88dfe45feb4c06a5cfb762"
},
"spaces": [{
"_id": {
"$oid": "5d88dfe45feb4c06a5cfb76f"
},
"name": "Building 2",
"subSpace": [{
"_id": {
"$oid": "5d88dfe45feb4c06a5cfb771"
},
"name": "Basement"
}, {
"_id": {
"$oid": "5d88dfe45feb4c06a5cfb770"
},
"name": "Floors"
}]
}, {
"_id": {
"$oid": "5d88dfe45feb4c06a5cfb76c"
},
"name": "Building 4",
"subSpace": [{
"_id": {
"$oid": "5d88dfe45feb4c06a5cfb76e"
},
"name": "Basement"
}, {
"_id": {
"$oid": "5d88dfe45feb4c06a5cfb76d"
},
"name": "Floors"
}]
}]
}
For this example, we want to delete the subSpace Floors in Building 2 with this _id : 5d88dfe45feb4c06a5cfb771
My code (in the model) :
exports.removeSubSpaceById = (subSpaceId) => {
Residence.findOneAndUpdate( { "spaces.subSpace._id": '5d88dfe45feb4c06a5cfb771' },
{ $pull:
{ spaces:
{ subSpace:
{ _id: '5d88dfe45feb4c06a5cfb771' }}}}, function(err, result) {
console.log(result);
})
};
Output : console.log : my entire document
But the subSpace/Basement (5d88dfe45feb4c06a5cfb771) is still in my document.
Thanks for your help.
Use positional operator for nested array operations. MongoDb Docs
exports.removeSubSpaceById = (subSpaceId) => {
Residence.findOneAndUpdate({ "spaces._id": '5d88dfe45feb4c06a5cfb76f' },
{
$pull:
{
"spaces.$.subSpace": { _id: "5d88dfe45feb4c06a5cfb771" }
}
}, function (err, result) {
console.log(result);
})
}
This is my router JS where I get document by Mongoose. So the thing is i have these nested data like oem, category and subcategory which I cannot get the whole details. I have been trying since one week but nothing complies with me. Can someone please help me out?
router.get("/product/:id/:product_id", (req, res) => {
ProReg.findById(req.params.id)
.populate({
path: "products",
populate: [
{
path: "products.oem",
model: "company",
select: "companyname"
},
{
path: "category",
model: "productcategory",
select: "category"
},
{
path: "subcategory",
model: "productsubcategory",
select: "subcategory"
}
]
})
.exec(function(err, products) {
if (err) {
res.json(err);
} else {
res.json(products);
}
});
});
This is the result that I am getting
{
"_id": "5cd37f4fcd79b01040124dbc",
"refno1": "klklklkl",
"refno2": "klklklkl",
"date": "2019-05-08T00:00:00.000Z",
"customer": "5c98bb0a42207b16d8fbd3cf",
"customertype": "5c7a1a1d4913fa08ac75c027",
"department": "5cbd67c709aeca1ea480157a",
"products": [],
"__v": 3
}
The details of the product is not coming only. Now how can i get this product data along with the details of oem, category, and subcategory?
Without Populate this is the result:
{
"_id": "5cd37f4fcd79b01040124dbc",
"refno1": "klklklkl",
"refno2": "klklklkl",
"date": "2019-05-08T00:00:00.000Z",
"customer": {
"_id": "5c98bb0a42207b16d8fbd3cf",
"customername": "Raghav"
},
"customertype": {
"_id": "5c7a1a1d4913fa08ac75c027",
"customertype": "Government "
},
"department": {
"_id": "5cbd67c709aeca1ea480157a",
"department": "Hardware"
},
"products": [
{
"warrantyfrom": "2019-05-09T00:00:00.000Z",
"warrantyto": "2019-05-30T00:00:00.000Z",
"oemwarrantyfrom": "2019-05-14T00:00:00.000Z",
"oemwarrantyto": "2019-05-14T00:00:00.000Z",
"_id": "5cd37f60cd79b01040124dbd",
"oem": "5cb6e026042460131454cf45",
"category": "5c960902e5cf3429e06beb6c",
"subcategory": "5ca35fbed6e1430df88954a6",
"modelno": "A123888",
"serialno": "fdsfdsfs"
},
{
"warrantyfrom": "2019-05-09T00:00:00.000Z",
"warrantyto": "2019-05-30T00:00:00.000Z",
"oemwarrantyfrom": "2019-05-14T00:00:00.000Z",
"oemwarrantyto": "2019-05-14T00:00:00.000Z",
"_id": "5cd37f65cd79b01040124dbe",
"oem": "5cb6e026042460131454cf45",
"category": "5c960902e5cf3429e06beb6c",
"subcategory": "5ca35fbed6e1430df88954a6",
"modelno": "A123888",
"serialno": "eeeeee"
},
{
"warrantyfrom": "2019-05-09T00:00:00.000Z",
"warrantyto": "2019-05-30T00:00:00.000Z",
"oemwarrantyfrom": "2019-05-14T00:00:00.000Z",
"oemwarrantyto": "2019-05-14T00:00:00.000Z",
"_id": "5cd37f6fcd79b01040124dbf",
"oem": "5c986a1e9b6bc614b8a551b9",
"category": "5c960902e5cf3429e06beb6c",
"subcategory": "5ca35fbed6e1430df88954a6",
"modelno": "QW123",
"serialno": "hhhhhh"
}
],
Did you try simply doing this?
ProReg.findById(req.params.id)
.populate('products.oem')
.populate('products.category')
.populate('products.subcategory')
.exec(function(err, products) {
if (err) {
res.json(err);
} else {
res.json(products);
}
});
});
Check out these related tickets:
Mongoose populate within an object?
Mongoose populate with array of objects containing ref
I had been searching around and still not able to find the correct answer.
Basically I have the below data model in mongodb
{
"_id": {
"$oid": "565db83bcd7bef020b1bdae8"
},
"userId": {
"$oid": "5653a3267827f178214918fc"
},
"targetUser": [
{
"userId": {
"$oid": "564663a5c0aefc151625b5e2"
},
"status": "Approved",
"_id": {
"$oid": "565db83bcd7bef020b1bdaea"
}
},
{
"userId": {
"$oid": "564548249bb75c600ff94cdd"
},
"status": "Sent",
"_id": {
"$oid": "565db884cd7bef020b1bdaed"
}
}
]
},
{
"_id": {
"$oid": "565db884cd7bef020b1bdaec"
},
"userId": {
"$oid": "564548249bb75c600ff94cdd"
},
"targetUser": [
{
"userId": {
"$oid": "5653a3267827f178214918fc"
},
"status": "Pending",
"_id": {
"$oid": "565db884cd7bef020b1bdaee"
}
}
]
}
How can I only return the follow data???
{
"userId": {
"$oid": "5653a3267827f178214918fc"
},
"targetUser": [
{
"userId": {
"$oid": "564663a5c0aefc151625b5e2"
},
"status": "Approved",
"_id": {
"$oid": "565db83bcd7bef020b1bdaea"
}
},
}
I had use the below code, but the result is return null
Connection.aggregate([
{$match:{userId:'5653a3267827f178214918fc'}},
{$unwind:'$targetUser'},
{$match:{'targetUser.status':'Approved'}},
{$group:{
_id:'$_id',
targetUser:{
$push:{
status:'$targetUser.status'
}
}
}}
],function(err,connections){
console.log(connections);
console.log(err);
})
Thank you so much for the help
From what I see, you don't need to aggregate, a simple find with a projection parameter will return what you need.
Connection.findOne({
userId: new ObjectId("5653a3267827f178214918fc")
}).select({
targetUser: {
$elemMatch: { status: "Approved" }
}
}).exec(callback);
But if you have more fields than userId and targetUser, you'll need to add them in the second parameter like this
Connection.findOne({
userId: new ObjectId("5653a3267827f178214918fc")
}).select({
targetUser: {
$elemMatch: { status: "Approved" }
},
oneMoreField: 1,
anotherField: 1
}).exec(callback);