MongoDB C# Driver - $match with the same field twice
-
20-12-2019 - |
Question
Suppose I have a collection of survey response documents that look like this:
{
_id: ...
surveryId: ...
created: ...
answers: [
{
"k" : "53ac9a031703670858aff600",
"v" : "Yes"
},
{
"k" : "53b1e8961703670aa858e4ec",
"v" : "75731431"
},
...
{
"k" : "53b1e8961703670aa858e4ee",
"v" : "71825"
}
}
How would I create aggregation match operator where "53ac9a031703670858aff600" equals "Yes" and "53b1e8961703670aa858e4ec" equals "75731431" using the C# driver?
I can run the following query in mongo shell and get the results I am looking for:
db.Records.aggregate([{ "$match" : {
"answers" : { "$elemMatch" : { "k" : "53ac9a031703670858aff600", "v" : "Yes" } },
"answers" : { "$elemMatch" : { "k" : "53b1e8961703670aa858e4ec", "v" : "75731431" } }
}}])
I try to express the same query in C# but get an error because of the duplicate answer key:
new BsonDocument("$match", new BsonDocument
{
{ "answers", new BsonDocument
{
{
"$elemMatch", new BsonDocument
{
{ "k", "53ac9a031703670858aff600" },
{ "v", "Yes" }
}
}
}
},
{ "answers", new BsonDocument
{
{
"$elemMatch", new BsonDocument
{
{ "k", "53b1e8961703670aa858e4ec" },
{ "v", "75731431" }
}
}
}
}
}
I have tried using a single answers element with a BsonArray of $elemMatch elements, but the resulting JSON does not return any results.
How can I express the above $match operator using the C# driver?
Solution
After taking a look at Multiple $elemMatch expressions for matching array values using $all in MongoDB? there should be one "answers" element and a $all to wrap each $elemMatch. So the correct $match operator should be:
db.Records.aggregate([{ "$match" : {
"answers" : { "$all": [
{"$elemMatch" : { "k" : "53ac9a031703670858aff600", "v" : "Yes" } },
{ "$elemMatch" : { "k" : "53b1e8961703670aa858e4ec", "v" : "75731431" } }
]}
}}])
Which makes the C# code look like this:
new BsonDocument("$match", new BsonDocument
{
{ "answers", new BsonDocument
{
{
"$all", new BsonArray
{
new BsonDocument("$elemMatch", new BsonDocument
{
{ "k", "53ac9a031703670858aff600" },
{ "v", "Yes" }
}),
new BsonDocument("$elemMatch", new BsonDocument
{
{ "k", "53b1e8961703670aa858e4ec" },
{ "v", "75731431" }
})
}
}
}
}
}
OTHER TIPS
try
var query = Query.And(
Query.EQ("Field1", "somevalue"),
Query.EQ("Field2", "somevalue")
);
or
var query = from e in collection.AsQueryable<Person>()
where e.Field1 == "someval" &&
e.Field2 == "someotherVal"
select e;
You could then loop further if need be
foreach (var thing in query)
{
/// access thing
}
or use cursor
var cursor = collection.FindAs<BsonDocument>(Query.EQ("field1", "value"));
cursor.SetFields(Fields.Include("otherfield"));
var items = cursor.ToList();
there's other ways but that all for today....