1

I have the following schema in my database:

{
   _id: Number,
   reagents: [ //Array of objects (embedded) FIND IF certain tag in v_class occurred only once in array
       {
           _id: Number,
           v_class: Array, //A single array (string only): ['TEST','PREMIUM']
       },
       {
           _id: Number,
           v_class: Array, //A single array (string only): ['TEST','PREMIUM']
       },
       {
           _id: Number,
           v_class: Array, //A single array (string only): ['TEST','PREMIUM']
       }
   ],
   other_fields: other_values,
}

MongoPlayground

The question is all about:

How to find only that documents, where reagents field have only one item (reagent, embedded documents), among v_class array field consist the word PREMIUM.

So from the selected collection above, I want to have only document with _id: 2 because it's the only document where reagents field have THE ONLY document, where in field called v_class word PREMIUM occurring only once.

UPD: I have achieved a bit simple results after $group stage, MongoPlayground (after group). So as for now, I still need to find docs where v_class array field occurring PREMIUM value exactly once in it's array`

UPD2: I have new version has appeared. MongoPlayground. This query is fine, but it shows all the PREMIUM except that occurred just once.

4
  • 2
    In your example, there is no document with a sigle PREMIUM in the v_class array of reagents. Commented May 5, 2020 at 17:38
  • 1
    Or do you want to find documents that have "premium" occurring exactly once in any of the v_classes (not is the only element of a v_class)? Commented May 5, 2020 at 17:43
  • @MickaelB. single doesn't mean that v_class array field will have only ["PREMIUM"] value, it means that I need to find only one doc, with v_class = consist PREMIUM so it could be like `['X', 'PREMIUM'] Commented May 5, 2020 at 17:44
  • @Oleg, y you right, thank you so much for pointing me out, I will correct the description. Commented May 5, 2020 at 17:45

2 Answers 2

1

$sum needs a numeric value to make sense.

Once you have the sum, an additional $match stage can compare the sum to 1.

https://mongoplayground.net/p/TKQowD-vd0f

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

5 Comments

I just found it: mongoplayground.net/p/JWWy8LPgk5j So the key question for now, how can I return the original doc by _id cause recipe_id field represents it in my case?
I imagine performing another $lookup to join the original collection to the existing results will achieve that.
What is your question?
There is no question there, actually you are right about $lookup stage cause at first I think that $out could return the original doc from the collection, but instead it creates a new collection of documents with a specific name.
1

I have found my own way to find the result, separately from Oleg, but he was first, so I upvote him and accept as answer his variant.

My query has the only one difference. It returns the original documents itself, not just reference fields.

Full query:

db.collection.aggregate([
  {
    $match: {
      reagents: {
        $elemMatch: {
          _id: 12
        }
      }
    }
  },
  {
    $group: {
      _id: {
        v_class: "$reagents.v_class",
        recipe_id: "$_id"
      },
      data: {
        $push: "$$ROOT"
      }
    }
  },
  {
    $unwind: "$_id.v_class"
  },
  {
    $match: {
      "_id.v_class": "PREMIUM"
    }
  },
  {
    $group: {
      _id: "$_id.recipe_id",
      count: {
        $sum: 1,

      },
      data: {
        "$first": "$data"
      }
    }
  },
  {
    $match: {
      count: 1
    }
  }
])

It finds the exact item in reagents (Array) field by ID, and it's document has a v_class (Array) field check if it's value/tag occurred only once.

MongoPlayground

Comments

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.