3

I'm new to MongoDB and have been struggling with this a bit. Let's say I have a document with an id, name, and array of objects:

{
    "_id": {
        "$oid": "614ba49b46727413d60b99e2"
    },
    "Name": 1,
    "ObjectArray": [
    {
        "ObjectId": {
            "$oid": "614ba49b46727413d60b99e3"
        },
        "Value": "some value", 
    }, 
    {
        "ObjectId": {
            "$oid": "614ba49b46727413d60b99e5"
        },
        "Value": "other value",
    }
    ],
}

I have a C# class that maps to this document and everything works in that regard. Let's say I want to add another object to the object array only if the new object's Id doesn't already exist in the array? I'm using C# Driver for this and have tried several things.

I've tried several ideas including the following --

var filter = FilterBuilder.Eq(x => x.Id, id) & 
             FilterBuilder.Nin(x => x.ObjectArray[-1].ObjectId, new[] { newDoc.ObjectId});

This unfortunately only checks the first object in the object array. So as asked before how do I only add a new object to an array if a condition exists all within one filter?

Thanks for your time.

*** Solution ***

Used Elematch in conjunction with Not to do the filtering all in one.

var filter = FilterBuilder.Eq(x => x.Id, id) & 
            FilterBuilder.Not(FilterBuilder.ElemMatch(x => x.ObjectArray, 
                 Builders<ObjectClass>.Filter.Eq(y => y.ObjectId, newDoc.ObjectId)));

1 Answer 1

2

You can use $elemMatch to access and filter nested property. And compare the value with $eq.

{
  "ObjectArray": {
    $elemMatch: {
      "ObjectId": {
        $eq: <value>
      }
    }
  }
}

Complete MongoDB aggregation query

db.collection.aggregate([
  {
    $match: {
      $and: [
        {
          "_id": {
            // With Exist _id
            $eq: ObjectId("614ba49b46727413d60b99e2")
          }
        },
        {
          "ObjectArray": {
            $elemMatch: {
              "ObjectId": {
                // With unexist ObjectArray.ObjectId
                $eq: ObjectId("614ba49b46727413d60b99e3")
              }
            }
          }
        }
      ]
    }
  }
])

Sample Mongo Playground

For MongoDB .NET/C# driver

var filter = FilterBuilder.Eq(x => x.Id, id) & 
             FilterBuilder.ElemMatch(x => x.ObjectArray, 
                 Builders<ObjectClass>.Filter.Eq(y => y.ObjectId, newDoc.ObjectId);

Replace ObjectClass with the class name for the Object in ObjectArray.

Remarks:

With the above solution, it will return the document when the parsed ObjectId is existed in ObjectArray. Hence you should do the handling for the existed ObjectId case.

And add the document to ObjectArray only when no document is queried.


References

  1. $elemMatch
  2. Similar scenario for filtering a document in an array with MongoDB .NET/C# driver
Sign up to request clarification or add additional context in comments.

1 Comment

Finally got it working with elematch for the c# driver. Had to use the Not function in conjunction with elematch. Thanks for your answer.

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.