3

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?

Brantino
  • 544
  • 1
  • 5
  • 15

2 Answers2

3

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" }
                                    })
                                }

                            }
                        }
                   }
              }
Community
  • 1
  • 1
Brantino
  • 544
  • 1
  • 5
  • 15
1

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....

fuzzybear
  • 2,325
  • 3
  • 23
  • 45
  • 1
    I need to be able to use a $match operator so that I can use the results of the $match in other steps in the aggregation pipeline. Also your code above is not using elemMatch, will it only return results that match both fields in the same sub document? – Brantino Jul 29 '14 at 01:17
  • 1
    last one is document, as in from a collection, middle one is collection but mapped to c# objects using linq, first one would return a collection, you could easily narrow it down using 2 then loop further, sorry dont know much about $match, but linq is the way to go IMHO, see this thread about aggregation and linq https://jira.mongodb.org/browse/CSHARP-383 and a tutorial http://mikaelkoskinen.net/mongodb-aggregation-framework-examples-in-c- – fuzzybear Jul 29 '14 at 01:23
  • 1
    As noted in the referenced MongoDB JIRA ticket, LINQ support for aggregations will not be available until the 2.0 version of the C# driver which as of this writing has not yet been released. – Brantino Jul 29 '14 at 01:46