Sorting and Deduplicating MongoDB Data with Reduce

I'm currently using the Reduce function to generate a combined String of fields from an array.

For instance, suppose I have an array of subdocuments named children - and each individual child contains a name field.

For example:

[
   {name:"Zak"}, {name:"Bob"}, {name:"Sharon"}, {name:"Zak"}, {name:"Cindy"}, {name:"Bob"}, {name:"Peter"}
]

By using the following expression, I can produce a "csv" of

"Zak, Bob, Sharon, Zak, Cindy, Bob, Peter,"
:

(Yes, I am aware that I could potentially utilize $cond to identify the last iteration and eliminate the trailing ", ".

  uniqueCsv: {
   $reduce: {
     input: "$children",
     initialValue: '',
     in: {
       $concat: ["$$this.name", ", ", "$$value"]
     }
   }
  }

Is there a way to use this reduce function to remove duplicates and alphabetically sort the names so that we end up with:

"Bob, Cindy, Peter, Sharon, Zak" ?

Thank you!

Answer №1

  • $setUnion is utilized here to extract unique elements from children.name and it also ensures that the strings are sorted in ascending order
  • $concat is used to combine strings with specific conditions. The first parameter is set as $$value, the second parameter involves a condition to check if the value is empty or not, and the third parameter is set as $$this which denotes the current string
db.collection.aggregate([
  {
    $project: {
      uniqueCsv: {
        $reduce: {
          input: { $setUnion: "$children.name" },
          initialValue: "",
          in: {
            $concat: [
              "$$value",
              { $cond: [{ $eq: ["$$value", ""] }, "", ", "] },
              "$$this"
            ]
          }
        }
      }
    }
  }
])

Check Playground


Another approach involves using $substr instead of $cond

  • $substr is used to manipulate the current reduce operation where the result will be , Bob, Cindy, Peter, Sharon, Zak
  • The objective is to remove the first 2 characters from the string. The second parameter signifies starting from the second position, and the third parameter indicates the length of the string - 1, which returns all strings
db.collection.aggregate([
  {
    $project: {
      uniqueCsv: {
        $substr: [
          {
            $reduce: {
              input: { $setUnion: "$children.name" },
              initialValue: "",
              in: {
                $concat: ["$$value", ", ", "$$this"]
              }
            }
          },
          2,
          -1
        ]
      }
    }
  }
])

Explore Playground

Important Note:

According to MongoDB, "$setUnion: The order of the elements in the output array is unspecified."

Although based on my personal experience, the output array is usually in ascending order. I have extensively used it in my projects and have consistently noticed an ascending order of strings as output.

Ultimately, it is your decision whether to incorporate this technique into your project without official confirmation from MongoDB.

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

Presentation: Troubleshooting Ineffective CSS3 Transitions

I have created a basic slideshow that can accommodate multiple images. Clicking on an image should move to the next slide, and once the last image is clicked, it should loop back to the first slide. The functionality of transitioning between slides seems ...

Using the filter() function in jQuery allows for efficient sorting and

My current area of study is in jQuery, but I'm encountering a bit of confusion with the following code: var list = mylist.filter(function(f) { return $(f) .find('.anthing') .length > 0; }); I'm particularly puzz ...

Exploring Node.js and Express routing: Strategies for managing client-side promises

I've been working on a routing issue with MongoDB where I'm having trouble retrieving data on the client side from the promise received via $resource. There's a button on the HTML page that triggers the following function on ng-click: $scop ...

Clicking again on the second onclick attribute

I have an image file named image1.png. When the button is clicked for the first time, I want it to change to image2.png. Then, when the button is clicked for a second time, I want it to change to yet another image, image3.png. So far, I've successful ...

Tips for concealing a collapsible navbar menu upon clicking elsewhere (Bootstrap 5)

I am trying to create a collapsible navbar menu: <div class="collapse navbar-collapse" id="navbarCollapsible"> .. menu items .. </div> My goal is to hide the menu whenever a user clicks outside of it (not just when click ...

Utilizing the combination of Mongodb and Mysql within a single project

For the past week, I've been dedicated to mastering Mongodb for my project. The main goal of my project is to store extensive geolocation data, and I believe that Mongodb is the most suitable database for this purpose. Speed is crucial for me, and Mon ...

Is it possible to determine if the process for changing Three.js material has been successfully completed?

Is it possible to determine the completion of this process? material.map = new THREE.Texture( canvas ); material.map.needsUpdate = true; If not, sometimes the final result will be a black snapshot. var snapshotData = renderer.domElement.toDataURL(strMi ...

Stripping away AM | PM from date variables

Is there a way to accurately calculate the difference between two datetime values in minutes without including AM|PM? When attempting to trim out the AM | PM from my code, I encounter errors (specifically NaN minutes). How can I safely remove this element ...

Would upgrading MongoDB from version 2.0.2 to 2.2 be a safe process with rollback contingency?

I'm considering upgrading MongoDB from version 2.0.2 to the latest release, but I have some concerns about running mongod with my current data files. If something were to go wrong during the upgrade process, would I be able to simply stop mongod and ...

Tips for properly formatting large numbers

I am facing a challenge with handling large numbers in my JavaScript code. I came across the nFormatter function for formatting large numbers but I am unsure how to integrate it into my existing code. Below is the nFormatter function that I found: functi ...

Cursor hovers over button, positioned perfectly in the center

I am facing a challenge with implementing a hover function for a set of buttons on the screen. The goal is to display the mouse pointer at the center of the button upon hovering, rather than the actual position of the cursor being displayed. I have tried u ...

Is it possible to efficiently bring in NPM packages with their dependencies intact in Deno?

I stumbled upon a helpful post outlining how to incorporate NPM modules in Deno: How to use npm module in DENO? The catch is, the libraries used in the example have absolutely no dependencies. But what if I want to utilize a dependency like Axios (not th ...

Using RTK Query to store data in a Firebase Realtime Database

Currently, I am facing an issue while trying to retrieve data from a Firebase Realtime Database using RTK Query. The code in this section is throwing an error because the return value is incorrect. If anyone has experience with this particular issue, I wou ...

Utilizing FullCalendar for showcasing comprehensive details

I'm a big fan of the fullcalendar plugin and all its amazing features. I want to enhance it by displaying more customized information for each event when in agendaWeek or agendaMonth view. Switching between views is easy, but I need help filtering out ...

Utilize express.static to showcase and fetch HTML content before serving JavaScript files

I'm having trouble getting my home.html file to display properly on the browser when I'm using express.static. Here is how my directory and file layout are structured: dir main -server.js dir subMain dir routing -routes.js ...

What is the significance of the source element in Vue3's audio element?

Playing mp3 files works in Vue 2, but not in Vue3. <template> <audio src="../file_example_MP3_700KB.mp3" controls ></audio> </template> In Vue3, the code needs to be modified as follows: <template> <audi ...

What causes getBoundingClientRect() in Javascript to occasionally produce decimal values?

Currently, I am experimenting with an HTML5 canvas element. A major concern of mine is setting up a mousemove event to monitor the movement of the mouse over the canvas for drawing and other purposes. Unfortunately, I have not been able to locate a definit ...

Troubleshooting Vue 3 Computed Property Not Updating

I'm currently facing a challenge while developing a login form using Vue 3. I am having difficulty in getting the state to update 'realtime' or computed. When attempting to login a user from the template, the code looks like this: <button ...

Using AngularJS, I can bind the ng-model directive to asynchronously update and retrieve data from

I am currently working with Angular to develop a preferences page. Essentially, I have a field in a mysql table on my server which I want to connect my textbox to using ng-model through an asynchronous xhr request for setting and fetching data. I attempt ...

What is the best way to retrieve an object that contains only specific embedded objects?

Here is the structure I am working with: { day: x, events: [ { year: y, info: z } ] } After creating a query, I noticed that it does not return any error but also does not display any results, which ...