-1

Suppose we have a mongodb collection with 2 columns: From, To. Now I would like to select rows where range From / To intersect with another range.

For example:

  • Object #1: From = 100, To = 200
  • Object #2: From = 150, To = 300
  • Object #3: From = 210, To = 230
  • Object #4: From = 290, To = 300
  • Object #5: From = 347, To = 349
  • Object #6: From = 400, To = 450

Now we have the range: 201 - 350. So in this range I have the objects in results:

  • Object #2
  • Object #3
  • Object #4
  • Object #5

and Object #1 / Object #6 not included into the selection result.

What is the query in this case?

2

1 Answer 1

1

Think using the aggregation query to achieve the result.

  1. $range - With the $range operator generate an array of numbers starting from 201 to 350.

  2. $filter - Filter the number within the From and To fields.

  3. $ne - Filter the document with the array generated from 2 is not an empty array.

db.collection.aggregate([
  {
    $match: {
      $expr: {
        $ne: [
          {
            $filter: {
              input: {
                $range: [
                  201,
                  350,
                  1
                ]
              },
              cond: {
                $and: [
                  {
                    $gte: [
                      "$$this",
                      "$From"
                    ]
                  },
                  {
                    $lte: [
                      "$$this",
                      "$To"
                    ]
                  }
                ]
              }
            }
          },
          []
        ]
      }
    }
  }
])

Demo @ Mongo Playground


Alternatively, works with $anyElementTrue and $map operators. You can apply in the .find() query.

db.collection.find({
  $expr: {
    $eq: [
      {
        $anyElementTrue: {
          $map: {
            input: {
              $range: [
                201,
                350,
                1
              ]
            },
            in: {
              $and: [
                {
                  $gte: [
                    "$$this",
                    "$From"
                  ]
                },
                {
                  $lte: [
                    "$$this",
                    "$To"
                  ]
                }
              ]
            }
          }
        }
      },
      true
    ]
  }
})

Demo 2 @ Mongo Playground

Sign up to request clarification or add additional context in comments.

9 Comments

Thanks a lot. And what mean "$$this" and can I change "aggregate" with "find"?
Hi @ValentinBorisenko, $$this is the variable that represents the iterated element in the array. It's normally used in these $filter, $map and $reduce operators that iterate each element in the array.
For .find() query, it should be achievable: Demo
How will the query change if we only have "from" or "to" at the range?
Do you mean that your document may not have From/To fields? If yes, it depends on your search criteria. If you want to bypass when either of the field not exist, you can check their existence with $type. Demo. Would be great to create another question post if you have different questions/requirements. Thanks.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.