MongoDB not in any array (nested arrays) - arrays

We have scheme like this
{
"_id" : ObjectId("5e2ebceb2fb28c43520ef313"),
"attempts" : [
{
"ideas" : [
{
"ideaId" : ObjectId("5d314e8ade83a139bf31352a"),
"ratings" : [
{
"userId" : "20-432-3",
"points" : 3.0,
"isBest" : true
}
]
},
{
"ideaId" : ObjectId("5d314e8ade83a139bf31352c"),
"ratings" : [
{
"userId" : "20-432-2",
"points" : 3.0,
"isBest" : true
}
]
},
{
"ideaId" : ObjectId("5d314e8ade83a139bf31352e")
}
]
}
]
I need to to update document only if it does not have given userId in attempts.ideas.ratings. For example when user with userId with "20-432-3" want to update document, it will fail (because there is already rating from him in first idea), on the other hand user with userId "20-432-1" can update document.
it's like 3 nested scheme, my question is: is it possible in one query???
thank you in advance
EDIT.
Found solution. Obviously it was the easiest way...
_id: ObjectId("5e2ebceb2fb28c43520ef313"),
"attempts.ideas.ratings.uuIdentity": { $ne: "20-432-1" }

Related

Compare array within objects in an array of the same Mongo document

I have a Mongo database with multiple documents and they all contain 2 Items for in store and online locations. The difference will be that attributes within the items object may differ. I am trying to capture all documents that have differing attributes between the object items with the array.
I've tried using $expr and comparing the position of the elements such as "Items.0.Attributes" == "Items.1.Attributes" but had no luck.
{
"ID" : "123456789",
"Items" : [
{
"ItemDept" : "softLines",
"ProductId" : {
"Name" : "shirts",
"_id" : "12345Shirts"
},
"Attributes" : [ "blue","small","mens"],
"Season" : "Summer"
"Location":"online"
}
,
{
"ItemDept" : "softlines",
"ProductId" : {
"Name" : "shirts",
"_id" : "12345Shirts")
},
"Attributes" : [ "blue","small","women"],
"Season" : "Summer"
"Location":"stores"
}
]
}
If I understand what you want to find/output, here's one way you could do it.
db.collection.find({
"$expr": {
"$not": {
"$setEquals": [
{"$first": "$Items.Attributes"},
{"$last": "$Items.Attributes"}
]
}
}
})
Try it on mongoplayground.net.

MongoDB query to retrieve a specific value from the document located in a array

I am trying to make a request in a document with mongodb.
In this document
{
"_id" : ObjectId("5bd19a92da24674fdabd26b6"),
"search" : "try",
"name" : "try",
"email" : "yes#gmail.com",
"password" : "$2a$10$YIRuApqDy/L8HU7R1k2SB.aC2hqH8xFDbl3/muF7PsoN6/SGzsH4q",
"color" : 0,
"profil" : "",
"banner" : "",
"desc" : "",
"date" : 45587899,
"friend" : [
{
"id" : ObjectId("5bcee588ae409f434d35c76c")
}
],
"groupes" : [ ]
}
I'm looking to get just the id in friend, not all of the document just 1 id in friend with where i try this :
db.users.find({$and:[{"friend.id":"ObjectId(5bcee588ae409f434d35c76c)"},{"search":"try"}]})
It's not working i got no result.
Thank you for helping me.
I am not 100% sure I do understand your question properly. You should be able to query the described document via the following query:
find(
/* query by 'search' and the specific friend-id */
{'friend.id': ObjectId("5bcee588ae409f434d35c76c"), search: 'try'},
/* return only that 'friend' element which matches the queried 'friend-id' */
{_id:0, friend:{$elemMatch:{id:ObjectId("5bcee588ae409f434d35c76c")}}}
)
You get the following result:
{
"friend" : [
{
"id" : ObjectId("5bcee588ae409f434d35c76c")
}
]
}
db.users.find({
friend: {
$elemMatch: {
id: ObjectId("5bcee588ae409f434d35c76c")
}
},
search: 'try'
})

Find and replace a sub sub array element in MongoDB

Hi I am developing MeteorJS app, I am stuck at updating a sub sub array element.
It is a poll application and I have the following database structure:
Under each question there are options and when a user clicks a button of an option, I want to increment that options votes by one and every user should have one vote right for each question.
From the button, I am passing name and questionId data in order to find the right option to increment vote. I should find the specific question with the questionId and then the specific array with the name under the Options.
Where I am stuck at is I can't find it.
Please help, thanks
Collection Name: Polls
Each Poll has the following structure:
{
"_id" : "uJtBt8mM2pbTYfwND",
"createdAt" : ISODate("2017-04-03T22:40:14.678Z"),
"pollName" : "First Poll",
"entryOwner" : "gdAHxDrxFuTvYiFt8",
"question" : [
{
"name" : "Question number 1",
"questionId" : "xgYQxGxpwBXaQpjXN",
"options" : [
{
"name" : "John",
"votes" : 0
},
{
"name" : "Adam",
"votes" : 0
},
{
"name" : "Robert",
"votes" : 0
}
]
},
{
"name" : "Question number 2",
"questionId" : "zviwYHHsaATBdG6Jw",
"options" : [
{
"name" : "John",
"votes" : 0
},
{
"name" : "Adam",
"votes" : 0
},
{
"name" : "Robert",
"votes" : 0
}
]
}
],
}
You can use $and which performs a logical AND operation on an array of two or more expressions.
{ $and: [ { <expression1> }, { <expression2> } , ... , { <expressionN> } ] }
The first expression here would be to get the question with questionId.
'question.questionId': "xgYQxGxpwBXaQpjXN"
And second expression to specify the object with matching name in options array.
To find the object with the name in options array, you can use $elemMatch which allows to specify queries.
{ <field>: { $elemMatch: { <query1>, <query2>, ... } } }
To get the object in options array having name as "John".
'question.options': {
$elemMatch: {
name: "John"
}
}
And finally, use $inc to increase the votes (here by 1).
It will get the first matching element (with $).
'question.options.$.votes': 1
Here's the full code:
db.Polls.update({
$and: [{
'question.questionId': "xgYQxGxpwBXaQpjXN"
},
{
'question.options': {
$elemMatch: {
name: "John"
}
}
}
]
}, {
$inc: {
'question.options.$.votes': 1
}
})

update nested array element value in node js mongoDB [duplicate]

This question already has answers here:
How to Update Multiple Array Elements in mongodb
(16 answers)
Closed 6 years ago.
Hi i am new in nodejs i need to update a value in nested array using _id of document my database document is look like this..
"complaints" : [
{
"complaint" : "head light is not working",
"complaintid" : ObjectId("57205219a56d2b8c0f9274a4"),
"_id" : ObjectId("57454c9249218eb40c1c0d1f"),
"labour" : 350,
"partCost" : 0,
"part" : [
{
"id" : ObjectId("56f12eaab915bd9800272ed7"),
"estimate" : 450,
"partname" : "clutch",
"_id" : ObjectId("57454cef49218eb40c1c0d25"),
"quantity" : 0,
"qrcodes" : []
},
{
"id" : ObjectId("56f12eaab915bd9800272ed7"),
"estimate" : 450,
"partname" : "rear tyre",
"_id" : ObjectId("57454cef49218eb40c1c0d24"),
"quantity" : 0,
"qrcodes" : []
}
],
"acceptance" : true,
"inspection" : false,
"color" : "#8929A9",
"status" : "APPROVED",
"estimate" : 1200,
"solution" : "HEAD LIGHT CHANGE",
"problems" : "HEAD LIGHT IS NOT WORKING"
},
i need to update quantity value of part array exist inside the part array using _id of part array
i am trying this but its not working what should i do for update this value...
var partdata = req.payload.parts;
for(var k = 0; k< partdata.length ; k++ ){
CPS.update({
'complaints.part._id' : partdata[k].partid
}, {
"$inc" : {
'complaints.part.$.quantity' : partdata[k].quantity
}
}).exec
(function(err,temp) {
if(err){
res(err).code(500);
}else{
console.log(temp);
}
});
}
MongoDB doesn't support matching into more than one level of an array.
Consider altering your document model so each document represents an
operation, with information common to a set of operations duplicated
in the operation documents.
Following is not the solution for your case.
But in-case you know the index then you could do something like this:
Assume a sample document like:
{
"_id" : ObjectId("57454c9249218eb40c1c0d1f"),
"part" : [{ "quantity" : 111 }, { "quantity" : 222 }]
}
Then this query should work.
db.test.update({ "_id" : ObjectId("57454c9249218eb40c1c0d1f") }, { "$set" : { "part.1.quantity" : 999 } })
Document will get modified as follows :
{
"_id" : ObjectId("57454c9249218eb40c1c0d1f"),
"array" : [{ "quantity" : 222 }, { "quantity" : 999 }]
}
Update: You can try following way of doing the update. But its not recommended way of doing probably you need to restructure your schema.
db.test.aggregate([
{ "$unwind": "$complaints" },
{ "$unwind": "$complaints.part" },
{ "$project":
{
_id: "$complaints.part._id",
partqty: "$complaints.part.quantity"
}
},
]);
This should return as follows:
{
"_id" : ObjectId("57454cef49218eb40c1c0d25"),
"partqty" : 111
}
{
"_id" : ObjectId("57454cef49218eb40c1c0d24"),
"partqty" : 222
}
Now you can use this information to update, e.g
var cur = db.test.aggregate([
{ "$unwind": "$complaints" },
{ "$unwind": "$complaints.part" },
{ "$project":
{
_id: "$complaints.part._id",
partqty: "$complaints.part.quantity"
}
},
]);
while (cur.hasNext()) {
var doc = cur.next();
//Note the index should be know again :|
db.test.update({ "complaints.part._id": ObjectId("57454cef49218eb40c1c0d25") },
{ "$set": { "complaints.$.part.1.quantity": 55 }},
{ "multi": true})
}

Adding object to array in array in MongoDB

I have this data structure (classes with comments) and I want to add a 1-level deep reply. This means that I'd like to add another object on a "comentarios" element.
How can I achieve this with mongo?
This means: Match cursada (db) id, match clase (first array) id, match comment (second array) id, then add a new element there.
db.cursada.find({"_id": ObjectId("55444f56e5e154f7638b456a")}).pretty()
{
"_id" : ObjectId("55444f56e5e154f7638b456a"),
"clases" : [
{
"_id" : "554e7f2fe5e154797d8b4578",
"titulo" : "qewewqewq"
},
{
"_id" : "554e8be0e5e154dc698b4582",
"titulo" : "la mejor clase"
},
{
"_id" : "554eb90de5e154dd698b458b",
"comentarios" : [
{
"_id" : ObjectId("55a021afe5e154cf098b4567"),
"nombreUsuario" : "nombre",
"texto" : "432432423"
}
],
"titulo" : "Peeling - cosa"
},
{
"_id" : "554e91a0e5e154797d8b4587",
"titulo" : "fdsfdsa"
},
{
"_id" : "554f8f50e5e154dd698b458f",
"titulo" : "clase2"
},
{
"_id" : "554f99dae5e154797d8b45a7",
"titulo" : "con profesor"
},
{
"_id" : "554fa4a0e5e154797d8b45c4",
"titulo" : "profesor nombre nombre"
},
{
"_id" : "5557b37be5e154e07f8b4567",
"titulo" : "Dermatologia I"
},
{
"_id" : "5557c701e5e154066d8b456c",
"titulo" : "Acido hialuronico"
}
],
"curso" : "552fa5f1e5e1542e628b4567",
"fechaFin" : "2015-05-22T03:00:00.000Z",
"fechaIni" : "2015-05-08T03:00:00.000Z",
"titulo" : "cremotas"
}
Getting this result:
{
"_id" : ObjectId("55444f56e5e154f7638b456a"),
"clases" : [
{
"_id" : ObjectId("554eb90de5e154dd698b458b"),
"comentarios" : [
{
"_id" : ObjectId("55a021afe5e154cf098b4567"),
"nombreUsuario" : "nombre",
"texto" : "432432423",
----------------HERE
"replies": [
{ "_id": ....,
"user": ....,
"text":....,
"date":....
}]
----------------HERE
}
],
"titulo" : "Peeling - cosa"
},
]
}
One twisted example!
Luckily it presents no problem to MongoDB and its $elemMatch query operator:
Model.update({
_id: "55444f56e5e154f7638b456a",
classes: {
$elemMatch: {
_id: "554eb90de5e154dd698b458b",
}
}
}, {
$push: {
'classes.$.comentarios': {
nombreUsuario: 'New comment nombreUsuario',
texto: '111242515'
}
}
}, function(err, count) {
console.log('Updated ' + count + ' document');
});
What happens here?
First, we're specyfing specific course ("cursada") to update:
_id: "55444f56e5e154f7638b456a"
Then, using $elemMatch operator, we're restricting result of the query to contain only one class:
classes: {
$elemMatch: {
_id: "554eb90de5e154dd698b458b",
}
}
Now, having found specific class to update, we can finally add new comment to it. Here's our update query:
$push: {
'classes.$.comentarios': {
nombreUsuario: 'New comment nombreUsuario',
texto: '111242515'
}
}
$push operator tells MongoDB to add new comment to specified array of comments.
'classes.$.comentarios' specifies which nested comentarios array to update, using $ positional operator.
Finally, and this part should be self-explanatory: full object of new comment to add to the specified class.
It's also worth mentioning that if you're running into such deeply nested structure, perhaps it's worth thinking about spreading courses, classes, possibly even comments over separate MongoDB collections.
When nested documents are the way to go and when it's better to create separate collections can be actually tricky question to answer - here's nice presentation discussing this issue.

Resources