Separate Various Document Arrays to Create Fresh Documents

Today I encountered a scenario where I needed to sync data from a mongoDB collection to Vertica (SQL Database) with the object keys serving as columns in the SQL table. To achieve this, I utilized the mongoDB aggregation framework to query, manipulate, and project the desired result document before syncing it to Vertica.

The schema that I aimed to aggregate is structured as follows:

{
  userId: 123
  firstProperty: {
    firstArray: ['x','y','z'],
    anotherAttr: 'abc'
  },
  secondProperty: {
    secondArray: ['a','b','c'],
    anotherAttr: 'def'
  }  
}

Given that the values within arrays are not directly related to one another, my objective was to have each value of a nested array within a separate result document. To achieve this, I implemented the following aggregation pipeline:

db.collection('myCollection').aggregate([
            {
                $match: {
                    $or: [
                        {'firstProperty.firstArray.1': {$exists: true}},
                        {'secondProperty.secondArray.1': {$exists: true}}
                    ]
                }
            },
            {
                $project: {
                    userId: 1,
                    firstProperty: 1,
                    secondProperty: 1
                }
            }, {
                $unwind: {path:'$firstProperty.firstAray'}
            }, {
                $unwind: {path:'$secondProperty.secondArray'},
            }, {
                $project: {
                    userId: 1,
                    firstProperty: '$firstProperty.firstArray',
                    firstPropertyAttr: '$firstProperty.anotherAttr',
                    secondProperty: '$secondProperty.secondArray',
                    seondPropertyAttr: '$secondProperty.anotherAttr'
                }
            }, {
                $out: 'another_collection'
            }
        ])

The expected result should look like:

{
  userId: 'x1',
  firstProperty: 'x',
  firstPropertyAttr: 'a'
}
{
  userId: 'x1',
  firstProperty: 'y',
  firstPropertyAttr: 'a'
}
{
  userId: 'x1',
  firstProperty: 'z',
  firstPropertyAttr: 'a'
}
{
  userId: 'x1',
  secondProperty: 'a',
  firstPropertyAttr: 'b'
}
{
  userId: 'x1',
  secondProperty: 'b',
  firstPropertyAttr: 'b'
}
{
  userId: 'x1',
  secondProperty: 'c',
  firstPropertyAttr: 'b'
}

However, the actual output is more like:

{
  userId: 'x1',
  firstProperty: 'x',
  firstPropertyAttr: 'b'
  secondProperty: 'a',
  secondPropertyAttr: 'b'
}
{
  userId: 'x1',
  firstProperty: 'y',
  firstPropertyAttr: 'b'
  secondProperty: 'b',
  secondPropertyAttr: 'b'
}
{
  userId: 'x1',
  firstProperty: 'z',
  firstPropertyAttr: 'b'
  secondProperty: 'c',
  secondPropertyAttr: 'b'
}

I am trying to pinpoint what exactly I am missing and how I can rectify the issue. Any insights would be greatly appreciated.

Answer №1

The problem at hand is more complex than it may seem initially. It all comes down to the use of "named keys," which can pose a challenge when handling data. Avoid using specific data points in key names to prevent confusion and repetition.

Another issue worth noting is the concept of a "cartesian product." When unwinding multiple arrays, you risk duplicating values from one array for each value in another. To address this, focus on combining arrays from a single source to streamline processing.

Different approaches exist based on your MongoDB version and practicality. Let's explore them:

Omit Named Keys

A straightforward solution is to omit named keys in the output and instead indicate their origin with a generic name like "name." By defining expected keys within an initial combined array and filtering out null values resulting from missing paths, you can simplify the aggregation process.

... ...

Conclusion

In situations where MongoDB lacks support for generating documents with distinct key names, options are limited. Consider utilizing the first approach without named keys or manually iterate cursor results to create a new collection with customized key-value pairs.

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

Preventing Users from Accessing NodeJS Express Routes: A Guide

Currently, I am working on a React application where I am utilizing Express to handle database queries and other functions. When trying to retrieve data for a specific user through the express routes like so: app.get("/u/:id", function(req, res) { ...

Include a fresh attribute to the objects within an array by referencing a distinct array

I have data stored in 2 arrays that contain objects. I want to create a new array by combining information from these two arrays using jQuery and Underscore. These are the structures of the original arrays: var orgArray = [ { "name": "phone", " ...

"Enhancing user experience with keyboard navigation using JavaScript

As a graphic designer, not a web developer, I am in the process of creating my portfolio website and would appreciate your patience. I am hoping to navigate between projects on my website using arrow keys on the keyboard. To implement this functionality, ...

Is it possible to utilize $regex alongside $all in mongoDB?

In my current project, I am facing a challenge where I need to handle an array of strings received from the frontend. Each document in my mongoDB database also has its own array of keywords. The tricky part is that the strings sent from the frontend migh ...

What causes the Invariant Violation: Invariant Violation: Maximum update depth exceeded error to occur when using setState()?

Looking for some help with this component: // here are the necessary imports export default class TabViewExample extends Component { state = { index: 0, routes: [ { key: 'first', title: 'Drop-Off', selected: true }, ...

What steps should I take to ensure that my website can recall the most recent interaction conducted by the user?

Our website features a search form that allows users to look for items on the page. In addition, there is a separate form with checkboxes that enables users to narrow down their searches in hopes of reducing the number of results returned. For example, i ...

Creating header menus with section labels in Windows 8 Metro can be easily accomplished by utilizing Javascript

Is there a way to create a navigation menu in Windows 8 Metro JavaScript that includes header menus and section labels, similar to the example shown below? ...

Utilizing Bootstrap and JavaScript/JQuery for enhancing functionality in Android applications

I created a website that functions well on Google Chrome and other popular browsers. Now, I am looking to publish it for Android using PhoneGap for conversion. A challenge I encountered was that PhoneGap no longer supports Bootstrap or JQuery. Could you pl ...

Tips for telling apart a drop from a drag abort

Upon completion of an HTML5 drag operation over another window, a Drop event occurs in the target window while a DragEnd event takes place on the dragged element in the source window. During both copy and move actions, the drop target carries out a copy o ...

Team member invitation feature on a MERN web platform

I've been working on a MERN stack website where every user who signs up will receive their own subdomain based on the username they choose. Progress so far: Users can successfully create accounts and obtain their personalized subdomains upon sign-up ...

JavaScript - Output an undefined value of a property within a function

While the question of checking for null or undefined values has been raised before, I am encountering a unique issue. I have created a function to split a string, which works perfectly. However, when I pass a null or undefined value, the program stops. Ins ...

Submitting a form from a non-AngularJS application to an AngularJS app requires URL rewriting

I am facing a challenge with my AngularJS search application. The search box is located on a standard HTML page that is not part of the AngularJS framework. Here is how the input field looks: <form accept-charset="UTF-8" name="search" id="search" act ...

Unable to dynamically add an element to a nested array in real-time

I'm currently developing an angular tree structure that contains a large nested array. nodes : public fonts: TreeModel = { value: 'Fonts', children: [ { value: 'Serif - All my children and I are STATIC ¯\ ...

Rockmongo appears to be devoid of any data

Even though MongoDB entries display 3889, they all appear to be empty. However, when attempting to retrieve the data through an API, it shows all the information. How is this possible and in what scenarios does this occur? ...

Update the parent node in the Google Org Chart

This is my first time working with Google Charts and I have a couple of questions: Is there a method in the API to update the parent of an existing node? I am facing a challenge where I need to build a tree structure top-down, which means that I know the ...

Issue with Typescript Application not navigating into the node_modules directory

After attempting to load the app from the root directory of our server, it became clear that this was not a practical solution due to the way our application uses pretty URLs. For instance, trying to access a page with a URL like http://www.website.com/mod ...

Unsupported feature: MongoDB Azure OPERATOR_PULL

Currently, I am utilizing Microsoft DocumentDB with Mongoose in my NodeJS application. At one stage, the application executes the subsequent code snippet: Scoreboards.findByIdAndUpdate(scoreboard.id, {$pull: {events: resp._id}}, function(err, raw){ ...

Discover the step-by-step process for moving data between collections in MongoDB

I am currently working on nestjs and have two collections, one for orders and the other for payments. My goal is to retrieve a single entry from the orders collection and save that same entry into the payments collection. Below is the code for the service ...

Modifying the location of an element in an array with jQuery

Using jQuery and JavaScript var movableItems = new Array(); movableItems.push($('#cloud1')); movableItems.push($('#comment1')); if(leftPressed == true){ for(var i = 0; i < movableItems ...

Using NextJS: Customizing page names for cleaner URLs

Currently working on a project in NextJS, I've come across an interesting observation. The file name within my pages folder seems to directly correspond to the path displayed in the URL bar. My question is, can I possibly create a structure like this ...