How do I write a strongly typed query filter where an array is a sub-array or equal to another array in MondoDB using C# driver?

Model:
{
_id: "1025",
CandidateName: "John"
Activities:["Programming", "Gaming"]
}
ChoicheOfActivities = ["Programming", "Gaming", "Singing", "Acting"];
Candidate1 = {_id:"1", Name: "John", Activities: ["Programming", "Gaming"]};
Candidate2 = {_id:"2", Name: "Mike", Activities: ["Programming", "Singing"]};
Candidate3 = {_id:"3", Name: "Joey", Activities: ["Gaming","Programming",  "Singing", "Acting"]};
Candidate4 = {_id:"4", Name: "Ross", Activities: ["Programming", "Kayaking"]};

I want to filter the candidates who have activities that are sub or equal set to the ChoiceOfAtivities. After applying the filter I want the results to be

Candidate1 = {_id:"1", Name: "John", Activities: ["Programming", "Gaming"]};
Candidate2 = {_id:"2", Name: "Mike", Activities: ["Programming", "Singing"]};
Candidate3 = {_id:"3", Name: "Joey", Activities: ["Gaming","Programming", "Singing", "Acting"]};

Candidate3 won't be selected because it has an activity "Kayaking" which is not in the ChoiceOfAtivities.

Note: I want to apply this when filtering not on a list or an Enumerable.

Upvotes: 1

Views: 101

Answers (2)

Kevin Smith
Kevin Smith

Reputation: 14436

@varman query is correct, however, this is how we'd express it as C#/.NET

We'd start by creating a class that represents our document:

class Candidate
{
    public string Id { get; set; }

    public string Name { get; set; }

    public string[] Activities { get; set; }
}

Then to get things started we'll just connect to mongo and insert your sample data in to the test database.

var client = new MongoClient();
var db = client.GetDatabase("test");
var collection = db.GetCollection<Candidate>("candidates");

var candidate1 = new Candidate { Id = "1", Name = "John", Activities = new[] { "Programming", "Gaming" } };
var candidate2 = new Candidate { Id = "2", Name = "Mike", Activities = new[] { "Programming", "Singing" } };
var candidate3 = new Candidate { Id = "3", Name = "Joey", Activities = new[] { "Gaming", "Programming", "Singing", "Acting" } };
var candidate4 = new Candidate { Id = "4", Name = "Ross", Activities = new[] { "Programming", "Kayaking" } };

await collection.InsertManyAsync(new[]
{
    candidate1,
    candidate2,
    candidate3,
    candidate4
});

Now we'll build up some filters using the filter builder.

var choiceOfActivities = new[] {"Programming", "Gaming", "Singing", "Acting"};


var filter = Builders<Candidate>.Filter.Not(
    Builders<Candidate>.Filter.ElemMatch(candidate => candidate.Activities,
    new BsonDocument("$nin", BsonArray.Create(choiceOfActivities))));

Then we can execute a find on our collection and get our the result

var results = await collection.Find(filter)
    .ToListAsync();

foreach (var result in results)
{
    Console.WriteLine($"{result.Id}, {result.Name}, {string.Join(" + ", result.Activities)}");
}
// 1, John, Programming + Gaming
// 2, Mike, Programming + Singing
// 3, Joey, Gaming + Programming + Singing + Acting

Upvotes: 3

varman
varman

Reputation: 8894

You can do like this way

db.collection.find({
  Activities: {
    $not: {
      "$elemMatch": {
        $nin: [
          "Programming",
          "Gaming",
          "Singing",
          "Acting"
        ]
      }
    }
  }
})

Working Mongo playground

Upvotes: 2

Related Questions