Search code examples
c#.netmongodbmongodb-.net-driver

MongoDB: Build query in C# driver


I stacked to build this Mongodb query in C# driver:

{ 
    Location: { "$within": { "$center": [ [1, 1], 5 ] } },
    Properties: {
        $all: [
            { $elemMatch: { Type: 1, Value: "a" } },
            { $elemMatch: { Type: 2, Value: "b" } }
        ]
    }
}

Something next:

var geoQuery = Query.WithinCircle("Location", x, y, radius);
var propertiesQuery = **?**;
var query = Query.And(geoQuery, propertiesQuery);

Addition:

The above query taken from my another question: MongoDB: Match multiple array elements You are welcome to take part in its solution.


Solution

  • Here's how if you want to get that exact query:

    // create the $elemMatch with Type and Value
    // as we're just trying to make an expression here, 
    // we'll use $elemMatch as the property name 
    var qType1 = Query.EQ("$elemMatch", 
        BsonValue.Create(Query.And(Query.EQ("Type", 1),
                         Query.EQ("Value", "a"))));
    // again
    var qType2 = Query.EQ("$elemMatch", 
        BsonValue.Create(Query.And(Query.EQ("Type", 2), 
                         Query.EQ("Value", "b"))));
    // then, put it all together, with $all connection the two queries 
    // for the Properties field
    var query = Query.All("Properties", 
        new List<BsonValue> { 
            BsonValue.Create(qType1), 
            BsonValue.Create(qType2)
        });
    

    The sneaky part is that while many of the parameters to the various Query methods expect BsonValues rather than queries, you can create a BsonValue instance from a Query instance by doing something like:

    // very cool/handy that this works
    var bv = BsonValue.Create(Query.EQ("Type", 1)); 
    

    The actual query sent matches your original request exactly:

    query = {
      "Properties": {
        "$all": [ 
            { "$elemMatch": { "Type": 1, "Value": "a" }}, 
            { "$elemMatch": { "Type": 2, "Value": "b" }}
        ]
      }
    }
    

    (I'd never seen that style of $all usage either, but apparently, it sounds like it's just not documented yet.)