Nayncore
Nayncore

Reputation: 243

Filtering a mongodb query result based on the position of a field in an array

Apologies for the confusing title, I am not sure how to summarize this.

Suppose I have the following list of documents in a collection:

{ "name": "Lorem", "source": "A" }
{ "name": "Lorem", "source": "B" }
{ "name": "Ipsum", "source": "A" }
{ "name": "Ipsum", "source": "B" }
{ "name": "Ipsum", "source": "C" }
{ "name": "Foo",   "source": "B" }

as well an ordered list of accepted sources, where lower indexes signify higher priority

sources = ["A", "B"]

My query should:

Example:

wanted_names = ['Lorem', 'Ipsum', 'Foo', 'NotThere']

Result:

{ "name": "Lorem", "source": "A" }
{ "name": "Ipsum", "source": "A" }
{ "name": "Foo",   "source": "B" }

The results don't necessarily have to be ordered.

Is it possible to do this with a Mongo query alone? If so could someone point me towards a resource detailing how to accomplish it?

My current solution doesn't support a list of names, and instead relies on a Python script to execute multiple queries:

db.collection.aggregate([
    {$match: {
        "name": "Lorem",
        "source": {
            $in: sources
    }}},
    {$addFields: {
        "order": {
            $indexOfArray: [sources, "$source"]
    }}},
    {$sort: {
        "order": 1
    }},
    {$limit: 1}
]);

Note: _id fields are omitted in this question for the sake of brevity

Upvotes: 1

Views: 666

Answers (1)

Valijon
Valijon

Reputation: 13103

How about this: With $group we have $min operator which takes lower source

Note: If you prioritize as ['B', 'A'], use $max then

db.collection.aggregate([
  {
    $match: {
      "name": {
        $in: [
          "Lorem",
          "Ipsum",
          "Foo",
          "NotThere"
        ]
      },
      "source": {
        $in: [
          "A",
          "B"
        ]
      }
    }
  },
  {
    $group: {
      _id: "$name",
      source: {
        $min: "$source"
      }
    }
  },
  {
    $project: {
      _id: 0,
      name: "$_id",
      source: 1
    }
  }
])

MongoPlayground

Upvotes: 1

Related Questions