1

I'm working with le latest C# MongoDB driver (2.4.4). I cannot find a way to filter a collection where all elements of a string array property are in another array (as an input parameter).

data : ["a", "b"] - input : ["a", "c", "b"] => OK

data : ["a", "b"] - input : ["a", "c"] => KO

Here is a ligh version of my model. I have a collection of shipments, each shipment has a string array of functions and subDocument array of shippingDocuments. Each shippingDocument also has a string array of functions.

shipment[]
   reference
   functions[]
   shippingDocument[]
           functions[]

I have a string array of functions in input paramaters (myFunctions). Basically I want to achieve this mongo shell command with the C# API with aggregation pipeline.

{$match:{"functions":{$in:myFunctions,$not: {"$elemMatch":{"$nin":myFunctions}}}}}

=> If a find a single element not in the input array it's KO.

I need to do the same thing with the shippingDocument array but it is perfectly fine with the $project.

var db = client.GetDatabase("ecom");
var collection = db.GetCollection<Shipment>("shipment");

var query = collection.Aggregate()
.Match(
    Builders<Shipment>.Filter.Eq(x => x.reference, "XXX") &
    (/*{$match:{"functions":{$in:myFunctions,$not: {"$elemMatch":{"$nin":myFunctions}}}}}*/) 
   )
.Project(s => 
    new
    {
        Reference = s.reference,
        Documents = s.shippingDocuments.Where(d => d.functions.All(ro => myFunctions.Contains(ro)))
    }
);

If a try to add the match,

Builders<Shipment>.Filter.Where(x => x.functions.All(f => myFunctions.Contains(f)))

I have an exception,

Unsupported filter: All({document}{functions}.Where(Contains(value(System.Collections.Generic.List`1[System.String])))).

Any ideas to achieve this ?

  • So is there something wrong with simply specifying the `$match` stage from a BSON document definition? Particularly considering the expression should be much more brief than trying to apply builders to do exactly the same thing. – Neil Lunn Sep 11 '17 at 09:08
  • I can't test it but can you write this: Builders.Filter.Where(x => !x.functions.Except(myfunctions).Any()) source: https://stackoverflow.com/questions/332973/check-whether-an-array-is-a-subset-of-another – BOR4 Sep 11 '17 at 09:40
  • It is perfectly fine in pure Linq but against MongoDB I get : Unsupported filter: Any({document}{functions}.Except(value(System.Collections.Generic.List`1[System.String]))). – user6691753 Sep 11 '17 at 09:46
  • @Neil, actually if I apply a filter with a BsonDocument as : BsonDocument.Parse($"{{'functions':{{$in:{myFunctions},$not: {{'$elemMatch':{{'$nin':{myFunctions}}}}}}}}}"); it works. But for developpers of my team, it would be quite easier to work with a "C#/Linq" approach. – user6691753 Sep 11 '17 at 13:44

0 Answers0