Retrieve an array field across various documents and combine the elements to form a single object

Consider a scenario where there is a users collection. Each user document includes an array of posts called posts. The goal is to query this collection as follows:

Retrieve 2 posts, starting at index Nstart and ending at index Nend, from each user in the username array: ['user1', 'user2']. Merge these posts into a single array, ordered by the ascending value of post.postedOn integer.

If we look at the example data:

{
  username: "user1",
  posts: [
    { id: 1, text: "123" ... },
    { id: 2, text: "456" ... },
    { id: 3, text: "789" ... },
    ...
  ]
},
{
  username: "user2",
  posts: [
    { id: 1, text: "abc" ... },
    { id: 2, text: "def" ... },
    { id: 3, text: "ghi" ... },
    ...
  ]
}
...

The desired output would be:

{
  posts: {
    { id: 1, text: "123" ... },
    { id: 2, text: "456" ... },
    { id: 1, text: "abc" ... },
    { id: 2, text: "def" ... },
  }
}

Attempts have been made with multiple uses of the aggregate function. One of the queries tried was:

db.getCollection("users").aggregate([{ $match: { username: { $in: ["admin", "admin2"] } } }, { $project: { posts: 1 } }])

However, this returns two user objects, each containing all of their posts instead of a single posts array that can be manipulated further.

The ultimate goal is to achieve the following:

Inputs

  • users: ['user1', 'user2']
  • starting posts index: 4
  • ending posts index: 8

Result

An array of posts from selected users, totaling 8 (IDs 4-8 from each user).

Answer №1

To achieve this, you need to utilize the aggregation operators $slice and $push. These operators help in selecting specific elements from a post array based on their index and adding them to a new array.

Consider a scenario where we have a collection named posts with three documents (excluding the _id field):

{
       "username" : "user2",
       "posts" : [
               {
                       "id" : 1,
                       "text" : "123"
               },
               {
                       "id" : 2,
                       "text" : "456"
               },
               {
                       "id" : 3,
                       "text" : "789"
               },
               {
                       "id" : 4,
                       "text" : "000"
               }
       ]
}
{
       "username" : "user1",
       "posts" : [
               {
                       "id" : 1,
                       "text" : "abc"
               },
               {
                       "id" : 2,
                       "text" : "def"
               },
               {
                       "id" : 3,
                       "text" : "ghi"
               },
               {
                       "id" : 4,
                       "text" : "zzz"
               }
       ]
}
{
        "username" : "user99",
        "posts" : [ ]
}

In the mongo shell:

> var users = [ "user1", "user2" ]
> var startIx = 1, noOfElements = 2

> db.posts.aggregate([ 
  { $project: { _id: 0, username: 1, posts: 1, usersMatch: { $in: [ "$username",  users ] } } },
  { $match: { usersMatch: true } },
  { $addFields: { posts: { $slice: [ "$posts", startIx, noOfElements ] } } },
  { $group: { _id: null, postsOfSelectedUsers: { $push: "$posts"} } },
  { $project: { _id: 0, selectedUsers: users, postsOfSelectedUsers: 1 } } 
])

The Result:

{
        "postsOfSelectedUsers" : [
                [
                        {
                                "id" : 2,
                                "text" : "456"
                        },
                        {
                                "id" : 3,
                                "text" : "789"
                        }
                ],
                [
                        {
                                "id" : 2,
                                "text" : "def"
                        },
                        {
                                "id" : 3,
                                "text" : "ghi"
                        }
                ]
        ],
        "selectedUsers" : [
                "user1",
                "user2"
        ]
}

NOTE: While this solution works, there may be room for further optimization or refinement.

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

Tips for effectively monitoring scope for data loading

I have successfully created a custom Angular directive that utilizes D3.js to create a visualization. In my HTML, I reference this directive as follows: <gm-link-analysis data="linkAnalysis.connections"></gm-link-analysis> The relevant part o ...

Refreshing a component using a sibling component in React

Currently, I am delving into the realm of React and embarking on a journey to create a ToDo App. However, I've hit a snag while attempting to add a new task to the list. Despite successfully adding an item to the list upon clicking the add button, upd ...

Generate JSON with a distinct structure

My goal is to send a JSON via POST request to an API in the following format: "answer" => { "name"=>"Test", "email"=>"<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="3d49584e497d49584e49135e52">[email  ...

Tips for emphasizing a specific cell in a row based on its expiration date

In my quest to find a script that colors dates within two weeks from today in red and past dates in orange, I have tried various methods without success. I am struggling to implement this feature with my current knowledge. <TABLE> <TR><TD&g ...

Exploring the method of accessing one Vue plugin from another plugin with the use of Vue.prototype

I'm currently working on developing a Vue plugin aimed at simplifying the management of authentication state throughout my application. This particular plugin will require interaction with other Vue plugins such as vuex, vue-router, and vue-apollo (fo ...

Problem arises with chai-http middleware when employing dynamic imports in chai 5.1.1 version

Currently, I am utilizing npm chai version 5.1.1 which has transitioned to supporting only imports and not requires. My use of dynamic imports has been successful so far. However, I have encountered an issue when incorporating the chai-http middleware with ...

Tips for identifying whether a form contains any empty fields and, if it does, directing focus to an anchor element

Is it possible to determine if a specific form contains any input fields? What about if it doesn't have any input fields? Additional Query: Also, how can I ensure that the focus is returned to a button when the page loads if the specified condition ...

Displaying foreign exchange rates using Shield UI Chart

In my quest to access and display forex data, I have stumbled upon the incredible Shield UI Chart. After some experimentation, I successfully mastered the art of implementing ajax: $.ajax({ url: 'http://api.apirates.com/jsonp/update', dataTy ...

When I try to run Parcel, my ReactJS website just won't deploy in a serverless environment

For a while now, I've been working on a website using serverless. Everything was going smoothly until this morning when I encountered an issue with pushing updates from my site to the serverless platform. When trying to push, I received the following ...

Transitioning jQuery .load and the usage of sorttable.js for sorting data

My jQuery code snippet is as follows: $("#loadBtn").click(function(){ $('#div1').delay(200).slideUp('slow') .load ('page2.php #div2').hide().delay(300).slideDown('slow'); return false; ...

The addition of special characters to strings in TypeScript through JavaScript is not functioning as expected

I need assistance on conditionally appending a string based on values from captured DOM elements. When the value is empty, I want to include the special character "¬". However, when I try adding it, I get instead because the special character is not reco ...

What is the best way to remove this .click function?

My goal is to create a switch function where clicking the "on" button changes its CSS, and if the user then clicks on the "off" button, the CSS returns to normal. I also need the switch to default to the "on" position, but my attempts so far have been unsu ...

A guide on organizing an array of objects by a specific property using a separate array

Here is the array I am working with: var arr = [ { count: 27, dataRil: "08/06/21", subCateg: "FISH", }, { count: 22, dataRil: "08/06/21", subCateg: "DOG", }, { count: 28, dat ...

What is the process for transferring npm package files to my local project?

Despite my efforts to find the answer, I couldn't locate it and so here I am asking again. What I'm looking for: I need to move a file from node_modules to my project in order to work on it. First attempt: I moved the file I wanted to edit An ...

Utilizing Dojo DGrid to customize the appearance of data within cells

I am facing an issue with my dgrid where I want to style cells by underlining the text when the checkboxes are selected for the row. My initial approach was to add a CSS class to the item once the checkbox is checked for the row. However, this method did ...

Why are the HTML links generated by JS not opening in Chrome?

<a href='http://www.xyz.hu/xyz' alt='Kosár' title='Kosár'>Megtekintés</a> Additionally: - A setInterval function refreshes the sibling's content every second, although it should not affect this specific el ...

Trigger an alert message upon loading the HTML page with search text

I need to search for specific text on a webpage and receive an alert if the text is found. <script type='text/javascript'> window.onload = function() { if ((document.documentElement.textContent || document.documentElement.innerText ...

inability to conceal a two-dimensional marker array within Google Maps API v3

I need some help with my marker that refuses to hide Even after using setMap, my marker is still visible on the map Here is the error message from the console Please assist! Thank you in advance markers[i][j].setMap(null); markers.setMap(null); va ...

Retrieving particular user information using meteor-presence

Is it possible to access specific user information (such as profile.name or other data stored within the profile object) using meteor-presence instead of just receiving the userId? Or, do I need to retrieve all userIds from Meteor.presences and then indi ...

What is the definition of a type that has the potential to encompass any subtree within an object through recursive processes?

Consider the data structure below: const data = { animilia: { chordata: { mammalia: { carnivora: { canidae: { canis: 'lupus', vulpes: 'vulpe' } } } } }, ...