Why is Robomongo returning an object from db.collection.distinct() instead of an array? - mongodb

Using the example from the MongoDB reference, I'd expect db.inventory.distinct("dept"); to return an array ["A", "B"], and that's exactly what happens when I run this from the shell. Using Robomongo (on OS X) I instead get an object with name-value pairs, like so: { "0" :"A", "1": "B" }.
This is the setup:
db.inventory.drop();
db.inventory.insert([
{ "_id": 1, "dept": "A", "item": { "sku": "111", "color": "red" },
{ "_id": 2, "dept": "A", "item": { "sku": "111", "color": "blue" },
{ "_id": 3, "dept": "B", "item": { "sku": "222", "color": "blue" },
{ "_id": 4, "dept": "A", "item": { "sku": "333", "color": "black" }
]);
Why is Robomongo behaving different? Can I do anything about it?

Related

Strange MongoDB $setIntersection behaviour

I want to query a match between records in my db based on certain tags. The match would be calculated based on a formula and the intersection of the tags. Now, even querying the intersection doesn't work...always. Sometimes it does, sometimes it doesn't. In my example, if I change the displayName attribute to something else (add or remove one character, the query works. In its current state (for demo purposes) it doesn't as it does not deliver the one intersection match for the last doc with id 3.
https://mongoplayground.net/p/KAYPoV29RFO
That's my query:
db.collection.aggregate([
{
$match: {
"_id": "1"
}
},
{
"$lookup": {
from: "collection",
let: {
"criteria": "$tags"
},
pipeline: [
{
$project: {
"match": {
$setIntersection: [
"$tags",
"$$criteria"
]
},
}
}
],
as: "result"
}
},
{
$project: {
"tags": 0
}
},
])
Here is the example data (simplified):
[
{ "_id": "1", "tags": [{ "_id": "a", "displayName": "a", "level": 1}, {"_id": "b", "displayName": "b", "level": 2}, {"_id": "c", "displayName": "c", "level": 3}]},
{"_id": "2", "tags": [{"_id": "a", "displayName": "a", "level": 1}, {"_id": "b", "displayName": "b", "level": 2}]},
{"_id": "3", "tags": [{"_id": "a", "displayName": "a", "level": 1}, {"_id": "d", "displayName": "d", "level": 4}]}
]
and the result as it is: (expected is three matches for id 1, 2 matches for id 2 and one for the last id. However, the last result has 0 elements in the intersection result. Again, when i change "displayName" to "displayNam" or "displayNames" (obviously in all docs), it give the correct result...
[{
"_id": "1", "result": [
{"_id": "1", "match": [{"_id": "a", "displayName": "a", "level": 1}, {"_id": "b", "displayName": "b", "level": 2},{"_id": "c","displayName": "c","level": 3}]},
{"_id": "2", "match": [{"_id": "a", "displayName": "a", "level": 1}, {"_id": "b", "displayName": "b", "level": 2}]},
{"_id": "3","match": [*here should be the match to _id: "a", but it's not (always) there*]}
]
}]
Does anyone have an idea what I am missing here?

MongoDb group by two conditions in aggregate

I would like to group my data by different conditions but I do not understand how I could do it.
My data:
[
{"Id": "1", "Info": "X" "Date": 10/1},
{"Id": "2", "Info": "X" "Date": 13/2},
{"Id": "3", "Info": "Y" "Date": 13/2},
{"Id": "4", "Info": "X" "Date": 10/1},
{"Id": "5", "Info": "X" "Date": 10/1},
{"Id": "6", "Info": "X" "Date": 13/2},
]
And I would like to group them by Info and by Date, a result similar to this one:
[
{"Id": ["1","4","5"], "Info": "X" "Date": 10/1},
]
[
{"Id": ["2", "6"], "Info": "X" "Date": 13/2},
]
[
{"Id": ["3"], "Info": "Y" "Date": 13/2},
]
I am using aggregate and I just know how to use aggregate to group them just by one condition, I donĀ“t know how to continue and how to use date in $group, this is what I have and how I group it by info:
.aggregate([
{ "$match" : { "$or": [{"status": "downloading"}, {"status": "calculating"}]}},
{ "$project": {"Id": 1, "Date": 1, "info": 1}},
{ "$group" : { "_id" : "$Info", "Id" : { "$addToSet" : "$Id"}}},
{ "$project": {"_id": 0, "Info": "$_id", "Id": 1 }}
You can give the _id in the $group stage multiple fields, like so:
db.collection.aggregate([
{
"$project": {
"Id": 1,
"Date": 1,
"info": 1
}
},
{
"$group": {
"_id": {
date: "$Date",
info: "$info"
},
"Id": {
"$addToSet": "$Id"
}
}
},
{
"$project": {
"_id": 0,
"Info": "$_id.info",
"Date": "$_id.date",
"Id": 1
}
}
])
Mongo Playground

MongoDB distinct returns empty

I can't get collection.distinct to work for me on db.version '4.4.3'. I'm following the example at https://docs.mongodb.com/manual/reference/command/distinct/
{ "_id": 1, "dept": "A", "item": { "sku": "111", "color": "red" }, "sizes": [ "S", "M" ] }
{ "_id": 2, "dept": "A", "item": { "sku": "111", "color": "blue" }, "sizes": [ "M", "L" ] }
{ "_id": 3, "dept": "B", "item": { "sku": "222", "color": "blue" }, "sizes": "S" }
{ "_id": 4, "dept": "A", "item": { "sku": "333", "color": "black" }, "sizes": [ "S" ] }
Then run
db.runCommand ( { distinct: "inventory", key: "dept" } )
I get
{ values: [], ok: 1 }
This doesn't work either:
db.inventory.distinct( "dept" )
[]
I can't get it to work on a local server or a remote server. What gives?

mongodb - filter collection by string array contains ""

For the below document, I want to write mongodb query to get the result.
[{
"id": "1",
"class": "class1",
"value": "xyz"
}, {
"id": "2",
"class": "class2",
"value": "abc"
}, {
"id": "3",
"class": "class3",
"value": "123"
}, {
"id": "4",
"class": "class4"
}, {
"id": "5",
"class": "class5",
"value": ""
}
]
The search parameter is an array of values - ["abc", "xyz", ""] and this is
going to look attribute "value"
The output should be below and in this case, the third item in the search array "" is pointing to collection that has "id" - 4 and 5 :
[{
"id": "1",
"class": "class1",
"value": "xyz"
}, {
"id": "2",
"class": "class2",
"value": "abc"
}, {
"id": "4",
"class": "class4"
}, {
"id": "5",
"class": "class5",
"value": ""
}
]
Please assist to provide the mongodb query to get the result like this
Whenever you have blank string you can add null in array, like this,
db.collection.find({
value: {
$in: ["abc", "xyz", "", null]
}
})

MongoDB - most efficient way to query and project matching nested array object

My doc structure in "test" collection looks like below:
{
"_id": "a1",
"t": [
{
"tId": "t1",
"do-not-project": "blah",
"b": [
{
"bId": "b1",
"name": "abc",
"do-not-project": "blah"
},
{
"bId": "b2",
"name": "def",
"do-not-project": "blah"
}
]
},
{
"tId": "t2",
"do-not-project": "blah",
"b": [
{
"bId": "b3",
"name": "ghi",
"do-not-project": "blah"
},
{
"bId": "b4",
"name": "jkl",
"do-not-project": "blah"
}
]
}
]
}
What's the most efficient way to query and project the below output if I know values for _id ("a1"), tId ("t2") and bId ("b3")? Aka only the matching nested array object and projected fields? Is this possible without aggregation at all?
{
"_id": "a1",
"t": [
{
"tId": "t2",
"b": [
{
"bId": "b3",
"name": "ghi"
}
]
}
]
}
According to MongoDB documentation, the find method has the following signature:
db.collection.find($query, $project)
So what you are looking for is probably something like:
db.collection.find(
{_id: "a1", "t"."tId": "t2", "t"."b"."bId": "b3" },
{"t"."tId": 1, "t"."b"."bId": 1, "t"."b"."name" :1}
)