Comparing max of column with another column - mongodb

I'm trying to compare two string columns in Mongodb using aggregate. My job is to list all docs which have a field(field1) greater than max of another field/column(field2).
db.collection.aggregate([
{"$match": {"id": "XXX"}},
{"$match": {"$expr": {'$gt': ["$field1", {"$max": '$field2'}]}}},
{"$project": {"id":1, "field1":1}}])
This doesn't seem to work. I'm using MongoDB 4.

Related

MongoDB: Filter fields returned by aggregation pipeline

I am performing the following aggregation pipeline, over a MongoDB collection:
# Define an aggregation pipeline
aggregation_pipeline = [
{"$match": {"business_id": query["business_id"], "dt_op": query["dt_op"]}},
{"$unwind": {"path": "$transactions"}},
]
How can I add a filtering step within the aggregation pipeline, in order to return only a selection of the document fields?
The equivalent with normal queries, using PyMongo, would be:
collection.find(
# Match data
query,
# Keep only columns of interest
{
"field_1": 1,
"field_2": 1,
"field_3": 1,
})

Count unique value of an object in array

I am trying to count the occurences of the field uuid in my collection. The dataset is a collection of Magic the Gathering decks. I want to see which cards are played the most. This is an example document in the collection:
_id:60aa430832f934a5874f7e3a
code:"JMP"
commander:Array
mainBoard:Array
name:"Rogues (1)"
releaseDate:"2020-07-17"
sideBoard:Array
type:"Jumpstart"
The uuid is located in a object in the mainBoard array. This would look like this:
mainBoard:Array[
{0:Object
artist:"Daarken"
...
uuid:"d99be31c-b176-530a-bb17-88056d2e06b1"}]
This is the aggregation I have tried without achieving my goal:
pipeline = [
{'$project': {"mainBoard": 1}},
{'$unwind': "$mainBoard"},
{'$group': {'_id': '$uuid', "count": {'$sum': 1}}},
{'$sort': {'_id': 1}},
]
# execute pipeline
for doc in database.deck_lists.aggregate(pipeline):
pprint(doc)
The aggregation above returns: {'_id': None, 'count': 22559}
What am I doing wrong?

Specific Field Wont Display In Mongo DB Aggregation Pipeline

I have a collection of Book Reviews where I am trying to find users who have created multiple reviews (lets say 5), I also want to return the number of reviews, their unique ID and their Name.
So far I have managed to find a way of doing this through aggregation, however for the life of me I cant seem to return the name field, I assumed a simple $project would be fine but instead I can only see the ID and the Number of reviews someone has made, what am i missing to fix this?
Current Code:
db.bookreviews.aggregate([
{"$group": {"_id": "$reviewerID","NumberOfReviews": { "$sum": 1 }}},
{"$match": {NumberOfReviews: {"$gte": 5}}},
{"$project":{_id:1,NumberOfReviews:1, reviewerName:1}},
])
Returned Values:
{IDXYZ, NumberofReviews 5},
{IDABC, NumberofReviews 5},
{ID123, NumberofReviews 5}
you can use $first to keep the first document of that group and keep the value of reviewerName in your $group stage and you can remove the $project.
db.bookreviews.aggregate([
{"$group": {"_id": "$reviewerID","NumberOfReviews": { "$sum": 1 }, "reviewerName": { "$first": "$reviewerName" } } },
{"$match": {"NumberOfReviews": {"$gte": 5}}},
])

How to count documents in pymongo with different names

I have a document formatted as below. I am trying to get most used command in discord and this is my mongodb collection format. I am using pymongo. Previously I used postgresql, but because of the problems in hosting, I shifted to mongodb.
Any help would be appreciated...
{
'guild': guild_id,
'channel': ctx.channel.id,
'author': ctx.author.id,
'used': message.created_at,
'prefix': ctx.prefix,
'command': command,
'failed': ctx.command_failed,
}
Now the problem is I want to fetch a query...
query = """SELECT command,
COUNT(*) as "uses"
FROM commands
WHERE guild_id=$1
GROUP BY command
ORDER BY "uses" DESC
LIMIT 5;
"""
I am searching this for hours, and still I didn't get the results..
You can use mongo aggregations
In your case it can be handled with the following mongo query:
db.getCollection('yourCollection').aggregate([
{$match:{"guild": guild_id}},
{$group:{_id: "$command", uses:{$sum: 1}}},
{$sort: {"uses": -1}},
{$limit: 5}
])
To adjust this query in pymongo you can take a look at here.
records = db.Collection.aggregate(
[{"$match": {"guild": guild_id}}, {"$unwind": "$command"},
{"$group": {"_id": "$command", "uses": {"$sum": 1}}},
{"$sort": SON([("uses", -1), ("_id", -1)])}, {"$limit": 5}])
records = await records.to_list(length=5)
Well this should be in case of python.

Index intersection issue in mongo

I'm using mongo 2.6.8 and have the following problem:
Collection users has indexes _id_1 and b_1. When I perform query
db.users.find({"$and": [
{"b": {"$gt": ISODate("somedate")}},
{"b": {"$lt": ISODate("anotherdate")}},
{"_id": {"$gt": "somevalue"}},
{"_id": {"$lt": "anothervalue"}},
]})
I expect that mongo will perform index intersection and will use intersected index, but it chooses only b_1 index. When executing explain on this query allPlans section even doesn't contain intersected index, only _id_1 and b_1.
Why does mongo not perform index intersection?
I think this could result from the fact, that you have two restrictions in your query on the same indexed key ($gt and $lt on b (and same for _id)). What happens to your explain if you change your query to the following. If It's using intersection I would be right:
db.users.find({"$and": [
{"b": {"$gt": ISODate("somedate")}},
{"_id": {"$gt": "somevalue"}},
]})
In this case using both restrictions on one index could be faster than using only one restriction of both indexes and use the intersection.