Strange behaviour with MongoDB sort operation - database

Here is the information collection and sample data:
Query to get all docs with eid:abc and sorted by role.
db.information.find({eid:"abc"}).sort({role:1}) giving expected
result, but when changing eid:aaa, result is not coming in sorting
order, order is random.
On contradictory when changing sort object to role:-1, its sorting
output in ascending order but then for eid:abc output comes in
descending order. it's just behaving strangely.
Using MongoDB shell version v4.0.6 :
information =[
{_id:'110',role:'dev',eid:'aaa',info:["a","b"]},
{_id:'111',role:'tester',eid:'abc',info:["a","b","c"]},
{_id:'112',role:'admin',eid:'abc',info:["a","c"]}
{_id:'113',role:'admin',eid:'abc',info:["a","b","c"]},
{_id:'114',role:'dev',eid:'abc',info:["a","b","c"]},
{_id:'115',role:'admin',eid:'aaa',info:["a","b","c"]}
];
Output:
1.when .find({eid:"aaa"}).sort:{role:1}
=>
[
{_id:'115',role:'admin',eid:'aaa',info:["a","b","c"]}
{_id:'110',role:'dev',eid:'aaa',info:["a","b"]},
];
2.when .find({eid:"abc"}).sort:{role:1}
=> [
{_id:'111',role:'tester',eid:'abc',info:["a","b","c"]},
{_id:'114',role:'dev',eid:'abc',info:["a","b","c"]}
{_id:'112',role:'admin',eid:'abc',info:["a","c"]}
{_id:'113',role:'admin',eid:'abc',info:["a","b","c"]}];
3.when .find({eid:"aaa"}).sort:{role:-1}
=>
[{_id:'110',role:'dev',eid:'aaa',info:["a","b"]}
{_id:'115',role:'admin',eid:'aaa',info:["a","b","c"]}]
4.when .find({eid:"abc"}).sort:{role:-1}
=>
[{_id:'113',role:'admin',eid:'abc',info:["a","b","c"]},
{_id:'112',role:'admin',eid:'abc',info:["a","c"]},
{_id:'111',role:'tester',eid:'abc',info:["a","b","c"]},
{_id:'114',role:'dev',eid:'abc',info:["a","b","c"]}]

This is what I got with a similar environment using Mongo Shell. The sort works fine for all four cases.
Note that the find query filter is on the field eid and the sort is applied on the field role.
> db.sorts.find()
{ "_id" : "110", "role" : "dev", "eid" : "aaa", "info" : [ "a", "b" ] }
{ "_id" : "111", "role" : "tester", "eid" : "abc", "info" : [ "a", "b", "c" ] }
{ "_id" : "112", "role" : "admin", "eid" : "abc", "info" : [ "a", "c" ] }
{ "_id" : "113", "role" : "admin", "eid" : "abc", "info" : [ "a", "b", "c" ] }
{ "_id" : "114", "role" : "dev", "eid" : "abc", "info" : [ "a", "b", "c" ] }
{ "_id" : "115", "role" : "admin", "eid" : "aaa", "info" : [ "a", "b", "c" ] }
> db.sorts.find({ eid: "aaa" }).sort({ role: 1 })
{ "_id" : "115", "role" : "admin", "eid" : "aaa", "info" : [ "a", "b", "c" ] }
{ "_id" : "110", "role" : "dev", "eid" : "aaa", "info" : [ "a", "b" ] }
> db.sorts.find({ eid: "abc" }).sort({ role: 1 })
{ "_id" : "112", "role" : "admin", "eid" : "abc", "info" : [ "a", "c" ] }
{ "_id" : "113", "role" : "admin", "eid" : "abc", "info" : [ "a", "b", "c" ] }
{ "_id" : "114", "role" : "dev", "eid" : "abc", "info" : [ "a", "b", "c" ] }
{ "_id" : "111", "role" : "tester", "eid" : "abc", "info" : [ "a", "b", "c" ] }
> db.sorts.find({ eid: "aaa" }).sort({ role: -1 })
{ "_id" : "110", "role" : "dev", "eid" : "aaa", "info" : [ "a", "b" ] }
{ "_id" : "115", "role" : "admin", "eid" : "aaa", "info" : [ "a", "b", "c" ] }
> db.sorts.find({ eid:"abc" }).sort({ role: -1 })
{ "_id" : "111", "role" : "tester", "eid" : "abc", "info" : [ "a", "b", "c" ] }
{ "_id" : "114", "role" : "dev", "eid" : "abc", "info" : [ "a", "b", "c" ] }
{ "_id" : "112", "role" : "admin", "eid" : "abc", "info" : [ "a", "c" ] }
{ "_id" : "113", "role" : "admin", "eid" : "abc", "info" : [ "a", "b", "c" ] }

Related

How to query Array in MongoDB?

i am new to MongoDB and I have documents as below
{ "_id" : ObjectId("604b7d62b19a72a2b89028e6"), "name" : "ram", "tags" : [ "mobile", "iphone", "india" ] }
{"_id" : ObjectId("604b7d83b19a72a2b89028e7"), "name" : "shyam", "tags" : [ "mobile", "iphone", "india" ] }
{ "_id" : ObjectId("604b7d9bb19a72a2b89028e8"), "name" : "ravi", "tags" : [ "mobile", "android", "india" ] }
{ "_id" : ObjectId("604b7db5b19a72a2b89028e9"), "name" : "aman", "tags" : [ "mobile", "android", "india" ] }
{ "_id" : ObjectId("604b7db5b19a72a2b89028e9"), "name" : "aman", "tags" : [ "windows", "usa" ] }
{ "_id" : ObjectId("604b7db5b19a72a2b89028e9"), "name" : "aman", "tags" : [ "tech", "apple", "microsoft" ] }
How to write query so that if i query for following tags ["mobile", "android", "12", "pro"] i would get following result
{ "_id" : ObjectId("604b7d9bb19a72a2b89028e8"), "name" : "ravi", "tags" : [ "mobile", "android", "india" ] }
{ "_id" : ObjectId("604b7db5b19a72a2b89028e9"), "name" : "aman", "tags" : [ "mobile", "android", "india" ] }
{ "_id" : ObjectId("604b7d62b19a72a2b89028e6"), "name" : "ram", "tags" : [ "mobile", "iphone", "india" ] }
{ "_id" : ObjectId("604b7d83b19a72a2b89028e7"), "name" : "shyam", "tags" : [ "mobile", "iphone", "india" ] }
Demo - https://mongoplayground.net/p/EMW8xgV1yrU
Use $in
The $in operator selects the documents where the value of a field equals any value in the specified array. To specify an $in expression, use the following prototype:
db.collection.find({
tags: { $in: [ "mobile", "android", "12", "pro" ] }
})

MongoDB - find any document with array combinations

mongo documents are like:
{
_id: '',
names: ['ab', 'bc']
}
{
_id: '',
names: ['ab', 'de', 'fg']
}
{
_id: '',
names: ['bc']
}
{
_id: '',
names: ['ab', 'bc', 'cd']
}
I have an input array:
['ab', 'bc', 'cd']
Question : How to get all the documents, where 'names' is equal to any combination of the input array ?
Result : all documents where 'names' is any of below should return
['ab']
['bc']
['cd']
['ab', 'bc']
['bc', 'ab']
['bc', 'cd']
['cd', 'bc']
... and so on..
['ab', 'bc', 'cd']
You can use $expr in find to get the $size of $setIntersection with names array
db.tt.find({$expr : {$gt : [{$size : {$setIntersection : ["$names", ["ab","bc","cd"]]}}, 0]}})
sample collection
> db.tt.find()
{ "_id" : "1", "names" : [ "ab", "bc" ] }
{ "_id" : "2", "names" : [ "ab", "de", "fg" ] }
{ "_id" : "3", "names" : [ "bc" ] }
{ "_id" : "4", "names" : [ "ab", "bc", "cd" ] }
with $expr and $setIntersection
> db.tt.find({$expr : {$gt : [{$size : {$setIntersection : ["$names", ["ab","bc","cd"]]}}, 0]}})
{ "_id" : "1", "names" : [ "ab", "bc" ] }
{ "_id" : "2", "names" : [ "ab", "de", "fg" ] }
{ "_id" : "3", "names" : [ "bc" ] }
{ "_id" : "4", "names" : [ "ab", "bc", "cd" ] }
with $in (as given in comments by Anthony)
> db.tt.find({names : {$in : ["ab","bc","cd"]}})
{ "_id" : "1", "names" : [ "ab", "bc" ] }
{ "_id" : "2", "names" : [ "ab", "de", "fg" ] }
{ "_id" : "3", "names" : [ "bc" ] }
{ "_id" : "4", "names" : [ "ab", "bc", "cd" ] }

update deeply nested array mongodb

I want to push one value in attachments array using mongodb. I want to update query using following criteria.
_id:ObjectId("5b56bd2f3e18580edc85af73") "cardID": ObjectId("5b56c895d0a04836f71aa776") "commentId":"2"
I want to push value in attachments, any help would be appreciated
This is a collection object:
{
"_id" : ObjectId("5b56bd2f3e18580edc85af73"),
"orgId" : "90",
"createdBy" : "test",
"name" : "testname",
"Cards" : [
{
"cardID" : ObjectId("5b56c895d0a04836f71aa776"),
"cardName" : "test Name",
"cardCreated" : "",
"reviewer" : "",
"priority" : "",
"cardPosition" : "",
"membersAssigned" : [
"ggg",
"fff"
],
"labels" : [
"l1",
"l2"
],
"description" : "",
"attachements" : [],
"comments" : [
{
"commentId" : "2",
"commentedBy" : "test",
"date" : "",
"comment" : "Hello world",
"attachements" : [
"1",
"data"
],
"emojis" : [
":smile:",
":thumbsup:"
],
"updatedBy" : "arkadata",
"updatedOn" : "",
"subComments" : {
"commentedBy" : "jaril",
"date" : "",
"comment" : "Hello world inside dark"
}
},
{
"commentId" : "3",
"commentedBy" : "test",
"date" : "",
"comment" : "Hello world",
"attachements" : [
"1",
"raj"
],
"emojis" : [
":smile:",
":thumbsup:"
],
"updatedBy" : "arkadata",
"updatedOn" : "",
"subComments" : {
"commentedBy" : "jaril",
"date" : "",
"comment" : "Hello world inside dark"
}
},
{
"commentId" : 6.0
}
],
"dueDate" : "",
"createdDate" : "",
"lastUpdated" : "",
"checkList" : [],
"position" : "5",
"status" : "active"
},
"timestamp" : ISODate("2018-07-24T05:46:23.890Z")
}
You can try with mongodb 3.6 arrayFilters
db.collection.update(
{ "_id": ObjectId(5b56bd2f3e18580edc85af73) },
{ "$push": { "Cards.$[card].comments.$[comment].attachments": "2" } },
{ "arrayFilters": { "card.cardID": ObjectId("5b56c895d0a04836f71aa776"), "comment.commentId": 2 } }
)
Make sure you cast your ids to ObjectId
Edit:
db.collection.update(
{ "_id": ObjectId(5b56bd2f3e18580edc85af73) },
{ "$push": { "Cards.$[card].comments.$[comment].attachments": "2" } },
{ "arrayFilters": [
{ "card.cardID": ObjectId("5b56c895d0a04836f71aa776")},
{"comment.commentId": 2 }
]
}
)

How do I do a '$all $in' on mongodb?

I have the following collection
>db.prueba.find({})
{ "_id" : "A", "requi" : null }
{ "_id" : "B", "requi" : null }
{ "_id" : "C", "requi" : [ "A" ] }
{ "_id" : "D", "requi" : [ "A", "B" ] }
{ "_id" : "E", "requi" : [ "C" ] }
{ "_id" : "F", "requi" : [ "B", "D"] }
{ "_id" : "G", "requi" : [ "F" ] }
I need each element of the requi field to be in the following array. in this case, the array has only one element
["A", "D"]
When I use the operator $all $in returns the following
>db.prueba.find({requi:{$elemMatch:{$in:['A','D']}}})
{ "_id" : "C", "requi" : [ "A" ] }
{ "_id" : "D", "requi" : [ "A", "B" ] }
{ "_id" : "F", "requi" : [ "B", "D" ] }
the query must returns only document, because 'B' not exists in the array ["A" , "D"]
{ "_id" : "C", "requi" : [ "A" ] }
please, help me
You can use $setIsSubset to check whether the given array is set of the requi array and then $redact to eliminate the non-matched ones.
db.collection.aggregate([
{ "$match": { "requi": { "$ne": null } } },
{ "$redact": {
"$cond": {
"if": { "$eq": [{ "$setIsSubset": ["$requi", ["A", "D"]] }, true] },
"then": "$$DESCEND",
"else": "$$PRUNE"
}
}}
])

the $elemMatch operator does not work correctly in mongodb

I have the following collection
>db.prueba.find({})
{ "_id" : "A", "requi" : null }
{ "_id" : "D", "requi" : [ "A", "B" ] }
{ "_id" : "E", "requi" : [ "B" ] }
{ "_id" : "B", "requi" : null }
{ "_id" : "C", "requi" : [ "A" ] }
I need each element of the requi field to be in the following array. in this case, the array has only one element
['A']
When I use the operator $elemMatch returns the following
db.prueba.find({requi:{$elemMatch:{$in:['A']}}})
{ "_id" : "D", "requi" : [ "A", "B" ] }
{ "_id" : "C", "requi" : [ "A" ] }
the query must returns only document
{ "_id" : "C", "requi" : [ "A" ] }
please, help me
Use $eq operator to find the exact match in the array
db.collection.find({ "requi": { "$eq": [ "A" ] } })
Output
[
{
"_id": "C",
"requi": [
"A"
]
}
]
Check it here

Resources