Ways to conduct a comparison of elements within an array within the same document

Is there a way to compare elements, by their index, within the same array in a MongoDB document? For example, consider the following entry:

{ "_id" : ObjectId("1"), "arr" : [ { "int" : 100 }, { "int" : 10 } ] }

I have a collection with numerous similar entries and I'm interested in querying the collection to identify those documents where the value of arr[0].int is greater than arr[1].int. It would also be helpful to determine the percentage difference between these two elements. For instance, in the given example,

index 1 is 10 times less than index 0
.

The query below successfully identifies elements in mongoDocs that are greater than a specified value:

db.collection.find( { "arr.0.int" : { $gt: 10 }})

I've experimented with different approaches but haven't found one that meets my requirements effectively, especially considering the large size of the dataset. Any insights on performance optimization would be greatly appreciated!

Thank you!

Answer №1

One way to handle this situation is by utilizing the $redact operator along with $arrayElemAt. This allows you to evaluate each index based on a specific condition.

db.collection.aggregate([
  { "$redact": {
    "$cond": {
      "if": {
        "$gt": [
          { "$arrayElemAt": ["$arr.int", 0] },
          { "$arrayElemAt": ["$arr.int", 1] }
        ]
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }}
])

The $cond operator within the pipeline stage checks if the specified condition is met, and includes or excludes documents accordingly. This method relies on native operators for optimal performance.

In MongoDB 3.6, a more concise syntax using $expr is available:

db.collection.aggregate([
  { "$match": { 
    "$expr": {
      "$gt": [
        { "$arrayElemAt": ["$arr.int", 0] },
        { "$arrayElemAt": ["$arr.int", 1] }
      ]
    }
  }}
])

This can also be used in a .find() operation:

db.collection.find({
  "$expr": {
    "$gt": [
      { "$arrayElemAt": ["$arr.int", 0] },
      { "$arrayElemAt": ["$arr.int", 1] }
    ]
  }
})

MongoDB supports JavaScript evaluation through $where, but it may not offer the same level of performance as native operators:

db.collection.find({
  "$where": "return this.arr[0].int > this.arr[1].int"
})

To calculate a ratio in the results, an aggregation pipeline must be used:

db.collection.aggregate([
  { "$redact": {
    "$cond": {
      "if": {
        "$gt": [
          { "$arrayElemAt": ["$arr.int", 0] },
          { "$arrayElemAt": ["$arr.int", 1] }
        ]
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }},
  { "$addFields": {
    "ratio": {
      "$divide": [
        { "$arrayElemAt": ["$arr.int", 1] },
        { "$arrayElemAt": ["$arr.int", 0] }
      ]         
    }
  }}
])

Consider storing common logic directly in your documents to avoid repetitive calculations. If that's not feasible, calculating conditions dynamically may be the only option, though it's important to assess the necessity of such calculations.

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

How to dynamically set a computed background image in Vue 2

I have several divs that I want to style with backgrounds from values stored in an array. My attempt to set the background overlay for each one by creating a computed property has not been successful: computed: { backgroundImage(url) { let ...

JavaScript and PHP are successfully displaying a success message despite the data not being saved to the database

I recently added a new feature to my website where users can submit a form using Javascript without having to reload or refresh the page. This allows for a seamless experience and displays success messages instantly. However, being a newcomer to Javascript ...

Removing a dynamic component in Angular

Utilizing Angular dynamic components, I have successfully implemented a system to display toaster notifications through the creation of dynamic components. To achieve this, I have utilized the following: - ComponentFactoryResolve - EmbeddedViewRef - Ap ...

Divide the Javascript code from the HTML Canvas

I have been diving into HTML5 Canvas and exploring how to implement it using Javascript code. However, I am facing difficulties separating the Javascript code from the original html file. Despite trying some solutions: HTML5 Canvas not working in extern ...

Purge ajax result upon completion of server operation

I'm currently working with an AJAX code that takes input from a radio form. The server code, upon satisfying a specific if() condition, redirects to another page on my site, such as dashboard.php! However, upon redirection, I am still seeing the rad ...

A guide on how to alternate between ng-hide and ng-show using separate controllers by utilizing a shared factory toggle state instance

Using Angular 1.x, I have implemented two controllers where I want to display controller_2 if controller_1 is hidden. To achieve this, I am utilizing a factory method. Here is the snippet of my HTML code:- <div ng-controller="controller_1 as c1" ng- ...

Pusher authentication issue: socket ID not defined

I am currently facing an issue while trying to establish a private channel for users to transmit data to my node.js server. Upon making the request, I encounter an error where pusher:subscription_error is returned with the error code 500. Upon checking my ...

Switch between showing the Font Awesome TitleText and its associated Class with a single click

Can the value of the title attribute for <i> be toggled? For example, if the title is set to <i title="Favorite This Post" class="fa fa-star-o" aria-hidden="true"> within <div class="postoption"> I would like to toggle both the title te ...

ways to undo modifications made to a value within an input field using jquery or javascript

$(document).ready(function () { //Highlight row when selected. $(function () { $('#Cases tr').click(function () { $('#Cases tr').removeClass('selectedRow'); $(this).addClass(&apos ...

Storing the results of an Ajax call in a global variable

What is the best way to store and access the output of an ajax call within a global variable? let globalOutput = []; $.ajax({ type: "GET", url: uri, dataType : "json", contentType: "application/json", data: { input: filterVa ...

AngularJS modifying shared factory object across controllers

Is it possible to update the scope variable pointing to a factory object after the factory object has been updated? In cases where there are 2 angular controllers sharing a factory object, a change made to the factory object by one controller does not re ...

Encountering a MODULE NOT FOUND error when using express.js

const express = require("express"); const app = express(); const path = require("path"); app.use(express.static(staticPath)); let staticPath=path.join(__dirname, ".."); There seems to be an error in these lines of ...

In React, when utilizing the grid system, is there a way to easily align items to the center within a 5 by

I need to center align items within the material-UI grid, with the alignment depending on the number of items. For instance, if there are 5 items, 3 items should be aligned side by side in the center and the remaining 2 items should also be centered. Pleas ...

Utilizing conditional statements within the array.forEach method to select specific sub-objects within an array of objects

Need help troubleshooting an if statement inside a function that is called by a forEach array loop. My array contains objects, with each object structured like this: arrofobj = [ {"thing_id":"1a", "val": 1, "Type": "Switch","ValType":{"0":"Open","1":" ...

Tips for deactivating data monitoring in a Vue.js component attribute

Looking to develop a Vue.js component that accepts properties from its parent component, like this example: <table-cell :value="foo" format="date" /> Although value and format are set as properties, Vue automatically sets up obse ...

Automatically refresh the Redux state in ReactJS at regular intervals to ensure the data is always up-to

I'm trying to implement a solution for running a background process in my React App, which will periodically call a backend API and update the redux state. The app is quite large with numerous components, so I need a global approach that doesn't ...

Is it possible to modify a portion of the zod schema object according to the value of a

My form consists of several fields and a switch component that toggles the visibility of certain parts of the form, as shown below: <Field name="field1" value={value1} /> <Field name="field2" value={value2} /> &l ...

How come I am unable to assign a value to my dropdown element following an AJAX request?

I am retrieving an array from session storage to act as a "saved" file. The data in the array is used to prepopulate input fields so users can continue where they left off. While all inputs populate correctly, dropdown elements do not. To retrieve options ...

What is the best way to eliminate all instances of the period symbol from an array?

How can I eliminate all instances of . from my array? var arr = ['...my name is apple', 'my girl .... friend is banana.......']; Below is the code snippet I am currently using. var arr = ['...my name is apple', 'my g ...

Expanding div width with jQuery as a percentage

Currently, I am facing a dilemma as I try to devise an equation for expanding the width of a div based on its current height. The Scenario Within this situation, there is a div that features a background image set to "contain." The original background ima ...