MongoDB - $sum, $limit and $sort in the same single query - mongo-shell

I am trying to write a single mongosh query on my customers database to:
Sum of the spend1 and spend2 fields;
Return only the top 10 userNames and totalSpends;
Descending order;
Limit of 10 collections.
Here is a couple of the collections in the database:
Atlas atlas-8qnlsq-shard-0 [primary] customers> db.customers.find();
[
{
_id: ObjectId("6387eed206cb28022d634cc4"),
userId: '500',
userName: 'robert.mcnaught',
firstName: 'Rab',
lastName: 'McNaught',
spend1: 10,
spend2: 15
},
{
_id: ObjectId("6387eef106cb28022d634cc5"),
userId: '501',
userName: 'robert.mcnaught',
firstName: 'Rab',
lastName: 'McNaught',
spend1: 10,
spend2: 15
}
]
From googling and manuals, I have come up with the following:
db.customers.find().limit(10).aggregate(
{
{$sort:{"$project":{
"spend1":"$spend1",
"spend2":"$spend2",
“totalSum”:{“$add”:[“$spend1”,”$spend2”]},
},-1});

Related

How do I return all results that don't contain a certain value in mongodb

I have some data in my mongodb database that looks similar to this:
[
{
username: 'will',
post: 'some random post',
user_id: '12345',
_id: 0
},
{
username: 'jogno',
post: 'some random post',
user_id: '23412',
_id: 1
},
{
username: 'aflack',
post: 'some random post',
user_id: '24332',
_id: 2
}
]
If my user_id is 12345, I want my query to return the other 2 posts where the user_id does NOT equal 12345. However when I use the query below it just returns all 3 posts, am I missing something or is there a different and better way to do this? Thanks
Post.find(
{ user_id: { $not: 12345 } }
)
SOLUTION:
I had to use $ne instead of $not
In your database, the user_id is a string, but in your query you are selecting a number.
Also, you should be using $ne for this.
Try $ne: "12345"

Indexing has no effect on db.find()

I've Just started to work with MongoDB, so you might find my question really stupid.I tried to search a lot before posting my query here, Any Help would be Appreciated.
I also came across this link StackOverFlow Link, which advised to apply .sort() on every query, but that would increase the query time.
So I tried to index my collection using .createIndexes({_id:-1}), to sort data in descending order of creation time(newest to oldest), After that when I used the .find() method to get data in sorted format(newest to Oldest) I did'nt get the desired result , I still had to sort the data :( .
// connecting db
mongoose.connect(dbUrl, dbOptions);
const db = mongoose.connection;
// listener on db events
db.on('open', ()=>{console.log('DB SUCESSFULLY CONNECTED !!');});
db.on('error', console.error.bind(console, 'connection error:'));
// creating Schema for a person
const personSchma = new mongoose.Schema(
{ name: String,
age : Number}
)
// creating model from person Schema
const person = mongoose.model('person', personSchma);
// Chronological Order of Insertion Of Data
// {name: "kush", age:22}
// {name: "clutch", age:22}
// {name: "lauv", age:22}
person.createIndexes({_id:-1}, (err)=>{
if (err){
console.log(err);
}
})
person.find((err, persons)=>{
console.log(persons)
// Output
// [
// { _id: 6026eadd58a2b124d85b0f8d, name: 'kush', age: 22, __v: 0 },
// { _id: 6026facdf200f8261005f8e0, name: 'clutch', age: 22, __v: 0 },
// { _id: 6026facdf200f8261005f8e1, name: 'lauv', age: 22, __v: 0 }
// ]
})
person.find().sort({_id:-1}).lean().limit(100).then((persons)=>{
console.log(persons);
// Output
// [
// { _id: 6026facdf200f8261005f8e1, name: 'lauv', age: 22, __v: 0 },
// { _id: 6026facdf200f8261005f8e0, name: 'clutch', age: 22, __v: 0 },
// { _id: 6026eadd58a2b124d85b0f8d, name: 'kush', age: 22, __v: 0 }
// ]
})
Indexes are special data structure, which can be used to run the queries efficiently. While running the query, MongoDB tries to see which index should be used for running the query efficiently and then that index will be used.
Creating an index with {_id:-1} will create an auxiliary data structure(index) which will be sorted newest first. It doesn't affect the order of the data which we are storing.
To sort the data in descending order(newest first) we will have to explicitly add the sort operation in your query and make sure that an index for descending order _id is present.

What is difference between partial indexes and sparse indexes mongodb?

I've read official docs of MongoDB but really can't understand the difference between sparse and partial indexes. I wanted to have an explanatory view with examples.
Sparse index is an optimized index which only contains pointers to documents that have value(s) in the indexed fields.
For example, let's say you would like to add an index on lastname field
{ _id: 1, firstname: 'John', lastname: 'Black', age: 20 }
{ _id: 2, firstname: 'Stive', lastname: 'White', age: 17 }
{ _id: 3, firstname: 'Tom', age: 22 }
if you run
db.users.createIndex({ lastname: 1 });
command, it will add indexes on 3 documents, but you don't need to have an index on a document where is no lastname value (_id: 3); it's a waste of space and memory.
To avoid empty fields' indexing, mongodb has sparse index, which is simply "check for non-empty value".
So when you add sparse: true
db.users.createIndex({ lastname: 1, sparse: true });
Mongodb will add indexes only for 2 documents (_id: 1, _id:2). Its great, but what if you want to index only those users' documents which are older than 18 years?
You cant use sparse index because it only checks documents for value existence.
This is why partial indexes were created.
db.person.createIndex(
{ age: 1},
{ partialFilterExpression: { age: { $gte: 18 }, lastname: { $exists: true }}
);
This example will put index only for 1 document(id: 1). Partial index is complex version of sparse, it will filter documents not only checking their existence, but using conditions provided in partialFilterExpression field.

update subdocument in MongoDB works in shell but not in Meteor application

I have a collection like this
{
_id: "qex6zPLgigq4KGpFP",
active: true,
name: "event name",
questions: [{
_id: "cff4cc7f1ae67282f1ea142b",
createdBy: "izRFAkhxgemihkRMF",
likes: 2
}, {
_id: "2cf23241ca456703f50a9ce4",
createdBy: "izRFAkhxgemihkRMF",
likes: 0
}]
}
and I initialize my collection in my Meteor application like this:
Events = new Mongo.Collection("events");
Now I want to remove a subdocument from the 'questions' array and it works in the shell with
db.events.update({_id:"qex6zPLgigq4KGpFP"}, {$pull: {'questions': {_id:"cff4cc7f1ae67282f1ea142b"}}})
but NOT in Meteor by calling
Events.update({_id:"qex6zPLgigq4KGpFP"}, {$pull: {'questions': {_id:"cff4cc7f1ae67282f1ea142b"}}})
The return value is always '1', but the document is still there.
It's confusing. Any ideas?

mongodb: order and limit the collection, then order and limit the resulting document nested documents

I have the following data structure on my game collection:
{
name: game1
date: 2010-10-10
media: [{
id: 1,
created: 2010-10-10 00:00:59
}, {
id: 2,
created: 2010-10-10 00:00:30
}]
},
{
name: game2
date: 2010-10-09
media: [{
id: 1,
created: 2010-10-09 00:10:40
}, {
id: 2,
created: 2010-10-09 09:01:00
}]
}
I want to get the game with the highest date, then get the related media with the highest created to get it's id. In the example above, the result would be
{
name: game1
date: 2010-10-10
media: [{
id: 1,
created: 2010-10-10 00:00:59
}]
}
I tried to use the find and find_one, and also aggregation, but I could not figure a way to make this query.
Any suggestions?
You will need to $unwind the media array in order to get the subdocument in that array where created is the highest then you $sort your documents by date and created all in descending order. Use $limit to output n documents which is 1 in our case.
In [26]: import pymongo
In [27]: conn = pymongo.MongoClient()
In [28]: db = conn.test
In [29]: col = db.gamers
In [30]: list(col.aggregate([{"$unwind": "$media"}, {"$sort": {"date": -1, "media.created": -1}}, {"$limit": 1}]))
Out[30]:
[{'_id': ObjectId('553323ec0acf450bc6b7438c'),
'date': '2010-10-10',
'media': {'created': '2010-10-10 00:00:59', 'id': 1},
'name': 'game1'
}]