How to construct aggregation of $setIsSubset with mgo - mongodb

I tried to construct a pipeline with mgo, but I have no idea about how to use $setIsSubset operator.
Here is the example from mongodb doc shows the usage of $setIsSubSet.
Is there anyone who can give me some tips? :-)
<code>
db.experiments.aggregate(
[
{$project: {A:1, B:1,AisSubset: {$setIsSubset: ["$A", "$B"]}, _id:0 }}
]
)
</code>
mongodb doc

Related

How to split a string field only if it exists in MongoDB?

I was trying to do something like the following
db.collection.updateMany(
{"obj.field": {$exists: true}},
{$set: {"obj.field": {$split: ["$obj.field", ", "]}}}
);
However, it seems $split is not supported in update. How can I split a string field only if it exists?
$split is an aggregation operator, not an update operator.
In order to use split in an update, you will need to pass an aggregation pipeline as the second argument to updateMany.
Since $set is both an update operator and an aggregation pipeline (alias for $addFields), that might look like:
db.collection.updateMany(
{"obj.field": {$exists: true}},
[{$set: {"obj.field": {$split: ["$obj.field", ", "]}}}]
);
Note that this require MongoDB 4.2+

How do I project an element of an array in mongo?

I have a mongo document that contains something like
{date: [2018, 3, 22]}
and when I try to project this into a flat JSON structure with these fields concatenated, I always get an array with 0 elements, eg. just extracting the year with
db.getCollection('blah').aggregate([
{$project: {year: "$date.0"}}
])
I get
{"year" : []}
even though matching on a similar expression works fine, eg.
db.getCollection('blah').aggregate([
{$match: {"$date.0": 2018}}
])
selects the documents I would expect just fine.
What am I doing wrong? I've searched mongo documentation and stackoverflow but could find nothing.
For $project you should use $arrayElemAt instead of dot notation which works only for queries.
db.getCollection('blah').aggregate([
{$project: {year: { $arrayElemAt: [ "$date", 0 ] }}}
])
More here

Mongodb aggregation sort on array primative

Given documents like
{
...
name:'whatever',
games: [122, 199, 201, 222]
}
db.col.aggregate({$match:{}},
{$sort:{'games.0': -1}})
doesn't sort ... no errors ... it just doesn't sort on the first array element of the games array.
Although a query with the same syntac .. works fine
col.find({}).sort({'games.0':-1})
if I change the collection so games is an array of objects like
[ {game1:198}, {game2:201} ...]
then the aggregation works using
{$sort:{'games.game1': -1}})
what am I missing to get this to work with an array of numbers?
Try unwinding the array first by applying the $unwind operator on the array, then use $sort on the deconstructed array and finally use $group to get the original documents structure:
db.coll.aggregate([
{"$unwind": "$games"},
{"$sort": {"games": 1}},
{
"$group": {
"_id": "$_id",
"name": {"$first": "$name"},
"games": {"$push": "$games"}
}
}
])
Try this:
db.coll.aggregate([
{"$unwind": "$games"},
{"$sort": {"games": -1}}
]}
I hope this will work for you as you expected.
In mongo 3.4 find sort i.e. db.col.find({}).sort({'games.0':-1}) works as expected whereas aggregation sort doesn't.
In mongo 3.6 both find and aggregation sort works as expected.
Jira issue for that: https://jira.mongodb.org/browse/SERVER-19402
I would recommend you to update your mongo version and your aggregation query will work fine.

How to invert a query in mongodb: $not

The mongo documentation says the $not operator does what I want, but it doesn't seem to be working:
The following returns a single document:
db.user.find({_id:ObjectId("51f09113cc0bd4a4a3958c96")})
This returns all 27 documents:
db.user.find()
This returns no documents:
db.user.find({$not:{_id:ObjectId("51f09113cc0bd4a4a3958c96")}})
So what am I doing wrong?
You should use $ne:
db.user.find({"_id" : {$ne: ObjectId("51f09113cc0bd4a4a3958c96") }})
Use $ne
db.user.find(_id: {$ne: ObjectId("51f09113cc0bd4a4a3958c96")})

Retrieve Array Of Documents in MongoDB

I have a MongoDB Document like as follows
{
"_id":1,
"name":"XYZ"
ExamScores:[
{ExamName:"Maths", UnitTest:1, Score:100},
{ExamName:"Maths", UnitTest:2, Score:80},
{ExamName:"Science", UnitTest:1, Score:90}
]
}
I Need to retrieve this document so that it has to show only Maths Array. Like as follows
{
"_id":1,
"name":"XYZ"
ExamScores:[
{ExamName:"Maths", UnitTest:1, Score:100},
{ExamName:"Maths", UnitTest:2, Score:80},
]
}
How Can I Do That ?
As #karin states there is no, normal, in query method of doing this.
In version 2.2 you can use $elemMatch to project the first matching result from ExamScores but you cannot get multiple.
That being said, the aggregation framework can do this:
db.col.aggregate([
{$unwind: '$ExamScores'},
{$match: {'ExamScores.ExamName':"Maths"}},
{$group: {_id: '$_id', name: '$name', ExamScores: {$push: '$ExamScores'}}}
])
Something like that anyway.
This has been asked before MongoDB query to limit values based on condition, the only answer there says it is not possible, but that there is a request to implement that.