i need to update one field from a subdocument that appears inside other documents for all documents...
Something like this, i have some documents like this:
{
"_id": { "$oid" : "531cc2410b4ebf000036b2d7" },
"name": "ALMACEN 2",
"items": [
{
"_id": { "$oid" : "531ed4cae604d3d30df8e2ca" },
"brand": "BJFE",
"type": 0,
"color": "GDRNCCD",
"hand": 1,
"price": 500,
"model": 0,
"qty": 24
},
{
"_id": { "$oid" : "531ed4cae604d2330df8e2ca" },
"brand": "BJFE",
"type": 0,
"color": "GDRNCCD",
"hand": 1,
"price": 500,
"model": 0,
"qty": 12443
},
{
"_id": { "$oid" : "531ed22ae604d3d30df8e2ca" },
"brand": "BJFE",
"type": 0,
"color": "GDRNCCD",
"hand": 1,
"model": 0,
"price": 500,
"qty": 5
}
]
}
I want to set the qty to 0 for all documents that contains the item with _id 531ed22ae604d3d30df8e2ca
At moment i have it
warehouses.update({$.items._id: new ObjectID(item.brand._id)}, { $set: { qty: 0}}, {safe: false, multi: true}, function (e) {
if (e) {
error(e);
return;
}
success();
});
But i think the query is not ok..
You'll need to use the "$" positional operator to achieve this:
db.warehouses.update({"items._id": "531ed22ae604d3d30df8e2ca"}, { $set: { "items.$.qty":0} } )
In the mongo console it would look like this:
do {
db.warenhouse.update(
{
"_id" : "531cc2410b4ebf000036b2d7",
items: {
$elemMatch: {
qty: { $ne: 0 }
}
}
},
{
$set: {
"items.$.qty": 0
}
}
)
} while (db.getPrevError().n != 0);
Resource link
Related
my problem is how I get a simple object of ownerDetails, correct me if my code is wrong
data I got, from my code
{
"status": true,
"data": [
{
"_id": "61a2a9680b122bc154cbd6af",
"ownerName": "Ajay",
"mobile": 878787878,
"designation": "IT",
"gender": "Male",
"age": 26,
"carDetails": [
{
"carName": "BUY",
"color": "blue",
"sheets": 8,
"avgSpeed": 105,
"price": 850000,
"model": "C110"
},
{
"carName": "GTR",
"color": "blue",
"sheets": 4,
"avgSpeed": 105,
"price": 98000,
"model": "G120"
}
]
}
]
}
i want data like this,
{
"status": true,
"ownerDetails": {
"_id": "61a2a9680b122bc154cbd6af",
"ownerName": "Ajay",
"mobile": 878787878,
"designation": "IT",
"gender": "Male",
"age": 26,
"total_car": 2,
}
}
code for getting data from collections
exports.getOwnerDetails = async (req, res, next) => {
try {
Owner.aggregate([
{
$match: { ownerName: req.body.ownerName }
},
{
$lookup: {
from: "cars",
localField: "ownerName",
foreignField: "ownerName",
as: "carDetails",
},
},
{
$project: {
"carDetails._id": 0,
"carDetails.ownerName": 0,
},
},
]).then((data) => {
res.json({
status: true,
data: data,
});
});
} catch (error) {
res.status(500).json({
status: false,
msg: "Error : " + error,
});
}
};
in may returning data, I got an array of carDetails, but I only need that how many are owned by an Owner, and return a simple object of ownerDetails
$lookup return an array because more than one values can match the join. If you want to get only one value you can get the first element from the array. Then you can add these aggregation stages:
First $addFields to get the first element from the array (index 0).
Then use $project to get the desired output.
{
"$addFields": {
"data": {
"$arrayElemAt": ["$data",0]
}
}
},
{
"$project": {
"status": 1,
"ownerDetails": {
"_id": "$data._id",
"ownerName": "$data.ownerName",
"mobile": "$data.mobile",
"designation": "$data.designation",
"gender": "$data.gender",
"age": "$data.age",
"total_car": {
"$size": "$data.carDetails"
}
}
}
}
Example here
Query
i am not sure if this is what you want
unwind all owners from data
and from each owner, count its cars number
Test code here
aggregate(
[{"$unwind": {"path": "$data"}},
{"$set":
{"data.total_car": {"$size": "$data.carDetails"},
"data.carDetails": "$$REMOVE",
"_id": "$$REMOVE"}},
{"$set": {"ownerDetails": "$data", "data": "$$REMOVE"}}])
Here is my MongoDB schema:
{
"_id": "603f23ff6c1d862e5ced9e35",
"reviews": [
{
"like": 0,
"dislike": 0,
"_id": "603f23ff6c1d862e5ced9e34",
"userID": "5fd864abb53d452e0cbb5ef0",
"comment": "Not so good",
},
{
"like": 0,
"dislike": 0,
"_id": "603f242a6c1d862e5ced9e36",
"userID": "5fd864abb53d452e0cbb5ef0",
"comment": "Not so good",
}
]
productID:"hdy6nch99dndn"
}
I want to use aggregate to get the review object of a particular id. I tried but not with any success.
Here is my code:
ProductReview.aggregate([
{ $match: { productID: productID } }
])
$match
$unwind
db.collection.aggregate([
{
$match: {
productID: 1
}
},
{
$unwind: "$reviews"
},
{
$match: {
"reviews._id": 2
}
}
])
Output:
[
{
"_id": ObjectId("5a934e000102030405000000"),
"productID": 1,
"reviews": {
"_id": 2,
"comment": "second comment",
"dislikes": [
{
"userID": 3
},
{
"userID": 4
}
],
"likes": [
{
"userID": 1
},
{
"userID": 2
}
]
}
}
]
Mongo Playground: https://mongoplayground.net/p/qfWS1rCuMfc
I have an array of values to update with existing array. I tried with $set it throws a error. If I have an array of values to update it should update matching item in the array.
1.If I have following documents in a collection
table
[
{
"id": 1,
"name": "Fresh Mart",
"products": [
{
"name": "Onion",
"qty": 10,
"price": "85"
},
{
"name": "Tomato",
"qty": 10,
"price": "85"
}
]
},
{
"id": 2,
"name": "Alfred super market",
"products": [
{
"name": "Onion",
"qty": 10,
"price": "85"
},
{
"name": "Tomato",
"qty": 10,
"price": "85"
}
]
}
]
Following query updates one product in first document:
Query
db.collection.update({
"$and": [
{
id: 1
},
{
"products.name": "Onion"
}
]
},
{
"$set": {
"products.name": "Onion Updated"
}
})
I tried to update both products in the first document with following query:
db.collection.update({
"$and": [
{
id: 1
},
{
"products.name": [ "Onion", "Tomato" ]
}
]
},
{
"$set": {
"products.name": "Onion Updated"
}
})
db.collection.update({
id: 1
},
{
"$addToSet": {
"products": {
"$each": [
{
"name": "Onion Updated",
"qty": 10,
"price": "85"
},
{
"name": "Tomato Updated",
"qty": 10,
"price": "85"
}
]
}
}
})
I used $addToSet it will not allow the duplicates. Is possible to replace existing value with $addToSet
but it didn't update the document.
This answer is the dynamic approach of this answer https://stackoverflow.com/a/49870042/8987128
Configure your payload
let id = 1;
let updateName = [
{
oldName: "Onion",
newName: "Onion Updated"
},
{
oldName: "Tomato",
newName: "Tomato Updated"
},
];
Prepare arrayFilters and set conditions
let arrayFilters = [];
let set = {};
updateName.forEach((v, i) => {
arrayFilters.push({ ["p"+i]: v.oldName });
set["products.$[p"+i+"].name"] = v.newName;
});
Update query
db.collection.update(
{ id: id },
{ $set: set },
{ arrayFilters: arrayFilters }
)
Playground
I have collection named "report" like this:
{
"_id" : ObjectId("5fc51722d6827f3bfd24e3b0"),
"is_deleted" : false,
"reporter" : ObjectId("5fb7b85f516b9709af5c7bc2"),
"violator" : ObjectId("5fb8a07e9cd2840f5f6bac5a"),
"reportNote" : "vi pham",
"status" : 0,
"createdAt" : ISODate("2020-11-30T16:00:34.013Z"),
"updatedAt" : ISODate("2020-11-30T16:00:34.013Z"),
"__v" : 0
}
With "reporter" and "violator" is ObjectID that reference from "User" collection
Now I want to find a list of violator and re-oder it from larger to small, so I do like this.
db.report.aggregate([
{ $group: { _id: "$violator", count: { $sum: 1 } } },
{ $sort: { count: -1 } }
])
And I have result as below.
{
"data": [
{
"_id": "5fb8a07e9cd2840f5f6bac5a",
"count": 10
},
{
"_id": "5fbcbe855e26df3af08ffcee",
"count": 7
},
{
"_id": "5fbcb990cb35042db064b2b0",
"count": 6
}
],
"total": 23,
"message": ""
}
My expected result is
{
"data": [
{
"_id": "5fb8a07e9cd2840f5f6bac5a",
"name": "David",
"email": "david#gmail.com",
"count": 10
},
{
"_id": "5fbcbe855e26df3af08ffcee",
"name": "Vincent",
"email": "Vincent#gmail.com",
"count": 7
},
{
"_id": "5fbcb990cb35042db064b2b0",
"name": "robert",
"email": "robert#gmail.com",
"count": 6
}
],
"total": 23,
"message": ""
}
I did follow turivishal recommend.
db.report.aggregate([
{ $group: { _id: "$violator", count: { $sum: 1 } } },
{ $sort: { count: -1 } },
{
$lookup:
{
from: "users",
localField: "violator",
foreignField: "_id",
as: "ViolatorDetail"
}
}
])
But the result of ViolatorDetail (User) is empty.
{
"data": [
{
"_id": {
"violator": "5fb8a07e9cd2840f5f6bac5a",
"status": 0,
"reportNote": "vi pham"
},
"count": 10,
"ViolatorDetail": []
},
{
"_id": {
"violator": "5fbcbe855e26df3af08ffcee",
"status": 0,
"reportNote": "vi pham"
},
"count": 7,
"ViolatorDetail": []
},
{
"_id": {
"violator": "5fbcb990cb35042db064b2b0",
"status": 0,
"reportNote": "vi pham"
},
"count": 6,
"ViolatorDetail": []
}
],
"total": 23,
"message": ""
}
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)
});