0

I was using the Equals(obj) method, but it's not working correctly because the array elements in the database are not ordered. If the order is different, it is not considered a matching element.

I tried that solution in two ways:

var filteredObj = objects.Find(obj => obj.Elements.OrderBy(x => x).Equals(elements)).FirstOrDefault();
var filteredObj = objects.Find(obj => obj.Elements.OrderBy(x => x).Equals(elements)).FirstOrDefault();

But in both of them I get the following exception:
Unsupported filter: {document}{Elements}.Equals(value(System.Collections.Generic.List[System.Int32]).OrderBy(x => x)).
It seems that MongoDb Driver doesn't support that kind of thing.

The method responsible for that:

public string GetIdByElements(List<int> elements)
{
    var filteredObj = objects.Find(obj => obj.Elements.Equals(elements)).FirstOrDefault();

    if (filteredObj is null)
        throw new ObjectNotFoundException("Object not found");
    return filteredObj.Id.ToString();
}
Felipe CS
  • 80
  • 10
  • You can use the [$setEquals](https://docs.mongodb.com/manual/reference/operator/aggregation/setEquals/) operator. – prasad_ Jul 23 '21 at 00:52
  • It seems to be what I need... Do you know if it is available for the C# Driver? Couldn't find nothing related to it. – Felipe CS Jul 23 '21 at 01:41

1 Answers1

1

You can use this Find query with the $setEquals operator as follows. Assuming the MongoDB colection's array filed name arrayField:

var elements = new List<int>() { 1, 34, 900 };    // input list
var bsonElements = new BsonArray(elements);
var query = 
    new BsonDocument("$expr",
           new BsonDocument("$setEquals", 
               new BsonArray {
                    "$arrayField",
                     bsonElements
                
           })
);

var doc = collection.Find(query).FirstOrDefault();
Console.WriteLine(doc);    // doc is of type BsonDocument

A sample collection's document with an array field: { "arrayField" : [ 1, 33, 900 ] }. The query in mongo shell to match the array elements using $setEquals operator (the order of the elements do not matter):

db.collection.find( { $expr: { $setEquals: [ "$arrayField", [ 1, 900, 33 ] ] } } )
prasad_
  • 12,755
  • 2
  • 24
  • 36
  • Thanks, it worked. In the documentation it says that "if an array contains duplicate entries, `$setEquals` ignores the duplicate entries.". Is there a workaround to this? I need to make that validation too. – Felipe CS Jul 23 '21 at 12:40
  • You want to consider exactly same number of elements in both the arrays as a match? – prasad_ Jul 23 '21 at 12:41
  • Actually I misunderstood it, it won't be needed. Thanks for the help! :) – Felipe CS Jul 23 '21 at 12:55