Sorting based on the number of elements in a filtered subdocument array

I have a MongoDB collection structured like this:

{
    {
        "_id": ObjectId,
        "user_id": Number,
        "updates": [
            {
                "_id": ObjectId,
                "mode": Number,
                "score": Number
            },
            {
                "_id": ObjectId,
                "mode": Number,
                "score": Number
            },
            {
                "_id": ObjectId,
                "mode": Number,
                "score": Number
            }
        ]
    }
}

My goal is to identify users with the highest number of updates per mode. For example, if I specify mode 0, I want to retrieve users based on the maximum number of updates with mode: 0.

Can MongoDB handle this type of query? While speed isn't a top priority, since the data will be cached and processed asynchronously for an extended period.

Answer №1

To increase efficiency, consider storing a count for each "mode" in the document as an additional field. This way, you can easily sort based on that count:

var update = { 
   "$push": { "updates": updateDoc },
};

var countDoc = {};
countDoc["counts." + updateDoc.mode] = 1;

update["$inc"] = countDoc;

Model.update(
    { "_id": id },
    update,
    function(err,numAffected) {

    }
);

This approach utilizes $inc to increment a "counts" field corresponding to each "mode" value when a new entry is added to the "updates" array. Sorting becomes efficient with this set-up:

Model.find({ "updates.mode": 0 }).sort({ "counts.0": -1 }).exec(function(err,users) {

});

If storing a count field is not feasible, another option is to calculate at query time using .aggregate():

Model.aggregate(
    [
        { "$match": { "updates.mode": 0 } },
        { "$project": {
            "user_id": 1,
            "updates": 1,
            "count": {
                "$size": {
                    "$setDifference": [
                        { "$map": {
                            "input": "$updates",
                            "as": "el",
                            "in": {
                                "$cond": [
                                    { "$eq": [ "$$el.mode", 0 ] },
                                    "$$el",
                                    false
                                ]
                            }
                        }},
                        [false]
                    ]
                }
            }
        }},
        { "$sort": { "count": -1 } }
    ],
    function(err,results) {

    }
);

While querying and calculating in real-time through .aggregate() is effective, it may not be as fast as having a pre-calculated count field.

The $map operator allows inline processing of array elements, combined with $cond for validation. Utilizing $setDifference ensures efficient filtering without unnecessary computation, unlike $unwind.

In conclusion, storing a count field is recommended for faster performance and potential index utilization.

Answer №2

It appears that this question may be a duplicate of the following:

Querying MongoDB for longest arrays inside an object

The solution provided in the accepted answer seems to address your query.

db.collection.aggregate( [
  { $unwind : "$values" },
  { $group : { _id : "$_id", count : { $sum : 1 } } },
  { $sort : { count : -1 } }
] )

Simply update "$values" in the code with "$entries".

[update:] Additionally, if you do not wish to limit the results to 25, you can remove the line { $limit : 25 } from the code snippet.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

React Hook is failing to trigger an update

Learning React and JavaScript has been quite a challenge for me, especially when it comes to understanding React Hooks and the issue of them not updating sometimes. I have tried searching online but either end up with solutions for class-based components o ...

What is the significance of using a double arrow function in Javascript?

Can someone explain the double arrow notation used in the code snippet below? How does the second arrow function get executed if the first one's response is true? And in what scenarios is this notation typically used? async check({ commit }) { ...

Discover the Maximum Total that is Below or Equal to a Specified Limit

Here is a function I am working with: var data = [12,23,14,35,24]; //debugger; function findMaxSum(dataArr, targetSum){ var currentSum = dataArr[0]; var maxSum = 0; var start = 0; for (var index = 1; index < dataArr.length; index++) { whi ...

Storing data from multiple pages onto the final page using C# and ASP.Net - step-by-step guide!

I need assistance with saving an application that spans across multiple pages. Instead of saving after each step, I would like to review a summary of all the pages on the final page before saving the complete application. Can someone please guide me throug ...

Align Bootstrap navigation bar items at the center horizontally

I am currently working on a navigation bar that features two icons, evenly distributed. To achieve this look, I have been experimenting with scaling the icons horizontally in order to make them center-aligned within the navigation bar. However, I have not ...

Executing PHP query after the Facebook Like button is clicked using Ajax code

Currently, I have the PHP code snippet below saved in a file named fblike.php. Another file houses the Facebook Like button, which is fully functional. My goal is to execute the code below whenever a user clicks on the Facebook Like button. I understand t ...

What is the method for getting my character to jump in Phaser 3?

I'm a beginner in Phaser 3 and I'm facing an issue with my character's jumping mechanic. Here is the code snippet I'm currently using: create() { this.player = this.physics.add.sprite(50, 380, 'idle'); this.player.set ...

Determining the Existence of a Model in Backbone/Marionette

I've built a simple backbone application, but I'm struggling with a more complex check that needs to be performed. Below is my code. I'm creating a list of chat participants. Eventually, I'll pass this list into a JavaScript function. ...

Navigating through the directories in PUG using the absolute path

Referring to the docs for PUG (), it states: If a path is absolute (example: include /root.pug), it gets resolved by prepending options.basedir. Otherwise, paths are resolved in relation to the file being compiled. To clarify, I understand that this in ...

How to extract a particular value from a JSON object using AJAX?

In my test.php file, I have implemented a code where ajax sends a request from index.php to this page. Within this page, I have created an array, converted it to JSON, and returned it as follows: <?php $arr = array( "status"=>200, "result"=>array ...

The session in Express.js is not retained across different domains

I am currently developing a third-party application that will be utilized across multiple domains. My main goal is to manage a session per user who uses the app, which led me to implement the express-session module for this purpose. However, I encountered ...

Tips for generating multiple instances of a JavaScript function on a single page

Consider the following JavaScript code snippet : var from,to; to = $(".range-to-dt").persianDatepicker({ inline: true, minDate: new persianDate(cleanDate(serverDateTime)), altField: '.range-to-dt-alt', altFormat: ...

When the state of the grandparent component is updated, the React list element vanishes in the grandchild component. Caution: It is important for each child in a list to have a unique

In my development project, I've crafted a functional component that is part of the sidebar. This component consists of 3 unique elements. ProductFilters - serves as the primary list component, fetching potential data filters from the server and offer ...

The value of Yargs.argv is consistently displayed as [object Object]

In my Ubuntu 16.04 environment, I enrolled in a node.js course on Udemy. Following the instructor's guidance, I initially used the exact version mentioned and later updated to the latest version (11.0.0). Surprisingly, both versions yielded the same o ...

It appears that the event listener attached with the ".on()" method has suddenly ceased functioning

Starting off, here is a link to my project on jsfiddle I will discuss how it's supposed to work and the main issue I am facing. The project consists of three "lines" represented at the top by a selector box. Each line has different "parts" displayed ...

"Encountering a hiccup with the Firebase service worker in Messaging and Firebase

I am interested in developing a small web application to explore the capabilities of Firebase Cloud Messaging for web apps. My intention is to utilize Firebase Hosting as the hosting platform for my app. ISSUE: Upon allowing the notification pop-up on my ...

Enhancing Vue JSX functionality: Tips and strategies

When working with JSX in Vue, it requires creating a dedicated file, whereas in React, we can use it inline within JavaScript. Is there a way to achieve this in Vue? Contents of .babelrc : { "presets": [ "@babel/preset-react&quo ...

Parsing JSON data as files are being read in an asynchronous manner

I have a task of reading multiple JSON files and consolidating their data into a single array. Here is my approach: const files = ['file0.json', 'file1.json', 'file2.json', 'file3.json'] To achieve this, I utilize ...

Unable to retrieve private field using a public getter method through a proxy

When retrieving data from a VueX Module using a Getter, the Object is enclosed within a Proxy that triggers the following error: TypeError: attempted to get private field on non-instance when attempting to access a private property with a public getter. ...

What is the best way to run multiple functions from an object?

My goal is to call all the functions that are contained within an object. const data = { fruits: funcA(), vegetables: funcB(), bread: funcC(), } The desired result looks like this: firstFunc(); dispatch(funcA()); dispatch(funcB()); dispatch(funcC() ...