Query performances with $in and $nin mongodb at scale

Viewed 23

I have 3 collections :

  • users
  • mappers
  • seens

Here is a document in users where "_id" is the id of a user and the ids array contains a list of other users _id :

{
  _id: "uid",
  ids: [
     "uid0",
     "uid5",
     ...
     "uid100"
  ]
}

A document in seens looks exactly like the one in users but in the ids array, there are ids of mappers that have been seen by the user, the "_id" is the one of the user owner of the array.

Here is a mapper where "_id" is the ID of a user and map.id is an id potentially existing in the ids field of a document of seens :

{
  _id: "uid",
  at: 1453592,
  map: {
    id: "uid",
    ...
  }
}

I want to retrieve all mappers that meet some conditions :

  • _id must be in the ids of the user
  • at must be $lt now and $gt than a given value (that is lower than now)
  • map.id must not be in ids of the seens of the user

The query looks like this :

{
  "_id": {"$in": ids},
  "$and": [
    {"at": {"$lt": now}},
    {"at": {"$gt": start_date}},
    {"map.id": {"$nin": seens}}
   ],
},

Where ids is the array of the user ids and seens is the array of the mappers already seen.

I have done some experiment on this query, it's working very fine with a thousands of records.

However, if i have 10 000 ids, 10 000 seens and 10 000 mappers and performing this query, it takes 15seconds. I have added an index on : at (descending) and map.id (ascending), it now takes 8sec.

I simply know that if my collections scale, this is only takes longer and longer.

How can i make it always returning results in less than 1sec not matter how many documents i have in my collections ? The underlying question is how to keep the query efficiency using $in and $nin at scale ?

0 Answers
Related