A Guide to Filtering MongoDB Data Using Array Values

I am trying to extract specific data from a document in my collection that contains values stored in an array.

{
  "name": "ABC",
  "details": [
     {"color": "red", "price": 20000}, 
     {"color": "black", "price": 22000}, 
     {"color": "blue", "price": 21000}
  ]
},
{
  "name": "XYZ",
  "details": [
     {"color": "yellow", "price": 10000}, 
     {"color": "black", "price": 12000}, 
     {"color": "green", "price": 11000}
  ]
},
{
  "name": "CBD",
  "details": [
     {"color": "red", "price": 30000}, 
     {"color": "pink", "price": 32000}, 
     {"color": "blue", "price": 31000}
  ]
}

I need help filtering the data for colors red and blue. The desired output is:

{"name": "ABC", "color": "red", "price": 20000},
{"name": "ABC", "color": "blue", "price": 21000},
{"name": "CBD", "color": "red", "price": 30000},
{"name": "CBD", "color": "blue", "price": 31000}

Can someone provide me with the MongoDB query or JS/TS code to achieve this?

Answer №1

If you want to achieve a specific format for your data, you can utilize the flatMap function as shown in the example below:

const information = [
  {
    "name": "XYZ",
    "details": [
       {"color": "green", "price": 25000}, 
       {"color": "yellow", "price": 26000}
    ]
  },
  {
    "name": "DEF",
    "details": [
       {"color": "purple", "price": 35000}, 
       {"color": "orange", "price": 36000}
    ]
  }
];

const modifiedData = information.flatMap(item => item.details.map(detail => ({name: item.name, ...detail})));

console.log(modifiedData);

Answer №2

If you want to flatten an array of complex objects with an array attribute, you can achieve this using Array.flatMap(). For reference, you can visit this link.

let data = [
{
  "name": "ABC",
  "details": [
     {"color": "red", "price": 20000}, 
     {"color": "black", "price": 22000}, 
     {"color": "blue", "price": 21000}
  ]
},
{
  "name": "XYZ",
  "details": [
     {"color": "yellow", "price": 10000}, 
     {"color": "black", "price": 12000}, 
     {"color": "green", "price": 11000}
  ]
},
{
  "name": "CBD",
  "details": [
     {"color": "red", "price": 30000}, 
     {"color": "pink", "price": 32000}, 
     {"color": "blue", "price": 31000}
  ]
}
]

data = data.filter(d1 => d1.details.some(d2 => d2.color == "red" || d2.color == "blue"))
data = data.flatMap(({ name,details }) => details.map(d => ({ name, ...d })))

console.log(data)

Answer №3

If you're looking to achieve optimal performance, this approach could be your go-to solution:

db.collection.aggregate([
   { $match: { "details.color": { $in: ["red", "blue"] } } },
   {
      $set: {
         details: {
            $filter: {
               input: "$details",
               cond: { $in: ["$$this.color", ["red", "blue"]] }
            }
         }
      }
   },
   { $unwind: "$details" },
   { $replaceWith: { $mergeObjects: [{ name: "$name" }, "$details"] } }
])

Explore Mongo Playground

Answer №4

If you're not concerned about performance, you have the option to execute the following JavaScript code:

let dataArr = [{
    "name": "XYZ",
    "details": [
       {"color": "green", "price": 50000}, 
       {"color": "yellow", "price": 51000}
    ]
  },

  {
    "name": "EFG",
    "details": [
       {"color": "purple", "price": 40000}, 
       {"color": "orange", "price": 41000}
    ]
  }
]
let finalArr = []
for (let j = 0; j < dataArr.length; j++) {
    for (let m = 0; m < dataArr[j].details.length; m++) {
        finalArr.push({title: dataArr[j].name, ...dataArr[j].details[m]})
    }
}

Answer №5

Utilizing the power of aggregation, this query can be incredibly beneficial.

db.collection.aggregate([
  {
    $unwind: "$details"
  },
  {
    $match: {
      "details.color": { $in: ["red", "blue"] }
    }
  },
  {
    $project: {
      _id: 0,
      name: 1,
      color: "$details.color",
      price: "$details.price"
    }
  }
]);

Answer №6

Utilizing MongoDB's $unwind operator can be beneficial for -

Breaking down an array field within the input documents to generate a document for each element. Each resulting document consists of the input document with the value of the array field substituted by the specific element.

An example of an aggregate query is shown below -

db.getCollection('your_collection').aggregate([
  // create a document for each element in `details` array
  { $unwind : "$details" },

  // filter document with color red or blue
  { $match: { "details.color": { $in: ["red", "blue"] } } },
  
  // output in desired format
  { $project: { name: 1, color: "$details.color", price: "$details.price" } }
])
  1. This showcases how the deconstructed data might appear -
[
  {"name": "ABC", "details": { "color": "red", "price": 20000} },
  {"name": "ABC", "details": { "color": "blue", "price": 22000} },
  {"name": "ABC", "details": { "color": "blue", "price": 21000} },
  {"name": "XYZ", "details": { "color": "yellow", "price": 10000} },
  {"name": "XYZ", "details": { "color": "black", "price": 12000} },
  ...
]
  1. Filtered and deconstructed data (limited to red & blue) -
[
  {"name": "ABC", "color": "red", "price": 20000},
  {"name": "ABC", "color": "blue", "price": 21000},
  {"name": "CBD", "color": "red", "price": 30000},
  {"name": "CBD", "color": "blue", "price": 31000}
]

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

To enable RTL in TextField, please note that the JssProvider is only available in "react-jss/src/JssProvider" and not in "react-jss/lib/JssProvider"

Seeking help to convert LTR to RTL in the following code: <TextField id="date" label="EmployeeDate" type="date" onChange= ...

Determine whether the response from a jQuery AJAX call is in JSON format or binary. If it is found to be binary, proceed

I am currently using ajax to retrieve and download an xlsx file from a PHP script. The script has two possible types of responses: JSON format if there are any warnings preventing the download (such as incorrect parameters), or the xlsx binary stream if ev ...

My application is functioning properly, yet Angular keeps throwing an error

I created a data filtering pipeline that functions perfectly, but I am encountering an error. Why is this happening? The error message: ERROR TypeError: Cannot read property 'filter' of undefined at FilterPipe.push../src/app/filter.pipe.ts. ...

New Middleware Integration: NextJS 14 AuthJS Social Provider Middleware - Automate MongoDB User Registration upon JWT Sign-In

I currently have a NextJS 14 application with AuthJS integrated to enable users to log in using social provider credentials only on a custom signin page. The JWT strategy in AuthJS is used for authentication because, as far as I know, the AuthJS MongoDB ad ...

Utilizing Meteor.js with MongoDB to efficiently query proximity based on GeoJSON Point coordinates within a specific longitude range, enhanced by Leaflet.js

Using Meteor.js and Leaflet.js, I was able to successfully display limited markers around the $near query of a "2dsphere" indexed Collection. To accomplish this, I indexed my GeoJSON coordinates: Locations._ensureIndex({'geometry.coordinates':&a ...

Efficient management of pre-built assets in Vite

I am currently developing a Vue application using Vite. Within the content folder, I have numerous files (ranging from 10 to 100) located as follows: content/block/paragraph.json content/block/theorem.json content/inliner/link.json ... My goal is to creat ...

Easiest Angular Carousel Solution

My goal is to create a basic Angular Carousel to enhance my understanding of Angular. While I have received helpful answers in the past, I am seeking further clarification to deepen my knowledge of Angular2+ and Typescript. Here's what I have so far: ...

What's the best way to customize the color of the text "labels" in the Form components of a basic React JS module?

I have a React component named "Login.js" that utilizes forms and renders the following:- return ( <div className="form-container"> <Form onSubmit={onSubmit} noValidate className={loading ? 'loading' : ''}&g ...

Is it possible to automatically close the modal by clicking outside of it

How can I make sure that my modal box only closes when clicking outside of it, and not when clicking on the buttons inside? I have a ref to the parent element that successfully closes the modal on click outside, but currently it also closes if I click on t ...

What is the best way to fill HTML tables using an ajax response?

This is a Laravel blade view/page that requires updating without the need to refresh the entire page. The blade.php code functions correctly and retrieves data from a MySQL database, but there seems to be an issue with the AJAX and JavaScript implementati ...

Dealing with CORS policy challenge

I am encountering an issue with Access to XMLHttpRequest at 'http://demo.equalinfotech.com/Iadiva/images/product/1634623781ladiva_barbara_01.glb' from origin 'http://localhost:8100' being blocked by CORS policy due to the absence of the ...

Getting an out-of-range exception (System.ArgumentOutOfRangeException) in C# Razor pages while attempting an AJAX call

I have a razor page model that contains a get-method. public IActionResult OnGetDuration([FromBody]int id) { Subject subject = _service.GetSubjectById(id); int duration = subject.LessonsPerWeek; return new JsonResult('a&apo ...

Scroll with Angular to Move Elements

Is there a way to convert this Jquery Code into an angularJs directive? http://jsfiddle.net/MMZ2h/4/ var lastScrollTop = 0; $("div").scroll(function (event) { var st = $(this).scrollTop(); if (st > lastScrollTop) { $('img').a ...

Utilize the power of Kotlin's Kmongo library by implementing abstract class collections

I have some model classes: abstract class Message : Data data class TextMessage(val message: String): Message data class ImageMessage(val image: ByteArray): Message I am looking to retrieve a collection based on the abstract class Message. database.getCol ...

Which medium is the optimal choice for file manipulation in Node.js and JavaScript?

Is there a simple way for JavaScript to receive incoming data from Node.js that was obtained from an external server? I've been searching for a solution to this problem for days now. Here's my current approach: I plan to have both the server-sid ...

Angular 2 property accessor designed similar to Linq style

Many times, we come across an array (IEnumerable) property where we need to extract specific values. In C#, we can achieve this by using the following code snippet: public AssetModel PromoImage { get { return Assets.FirstOrDefa ...

How to implement form modal binding using Laravel and Vue.js

There are two models named Tour.php public function Itinerary() { return $this->hasMany('App\Itinerary', 'tour_id'); } and Itinerary.php public function tour() { return $this->belongsTo('App\Tour', ...

Creating a three-dimensional shape using a transparent image in Three.js

Hey there! I'm currently working on creating a 3D model that features the upper and lower sides as transparent images, while the other sides are a solid color (yellow in this case). var texture = new THREE.TextureLoader().load( 'img.png' ); ...

What is the best way to implement lazy loading of images that have not been downloaded in a JavaFX WebView?

Currently, I am in the process of developing an email client application using JavaFX WebView to showcase email HTML files. In order to enhance its responsiveness and speed, my goal is to display inline images in emails as they are downloaded locally. Duri ...

What causes the discrepancy between the values returned by the jQuery getter css() method and JavaScript when accessing the style variable

After recently beginning to use jquery, I decided to switch due to initialization issues when loading external styles with javascript. Here is a rule defined in an external style sheet: #siteLogoDiv { position:absolute; left:0px; top:0px; width:100%; heig ...