13

This seems so basic that I'm sure I've just overlooked a class or a method somewhere, but for the life of me, I can't find it.

I've got a json string like so:

{ SendId: 4, "Events.Code" : { $all : [2], $nin : [3] } }

I can run this in the mongo shell against a find() or a count() and get what I'm looking for. What is the easiest way to deal with this in C#? Here's what I've found:

  • The methods I'm finding are all wanting an IMongoQuery, which is just a marker interface
  • BsonDocument has a nice Parse method, but it doesn't implement IMongoQuery
  • QueryDocument inherits from BsonDocument, and it does implement IMongoQuery, but it does not have it's own Parse method, and I can't convert the QueryDocument to BsonDocument
  • The Aggregation framework takes a BsonDocument[], but sometimes I just want a simple Find or Count operation
  • Some of these queries are large and gross, and I don't want to build them a line a time with the Query builder class

If the database deals with json documents, and I can run this stuff in the shell, isn't there some way to run it through the driver?

2 Answers 2

17

It's ugly, but you can do this by deserializing the string in to a BsonDocument and then wrapping in a QueryDocument

BsonDocument query = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>("{ SendId: 4, 'Events.Code' : { $all : [2], $nin : [3] } }");
QueryDocument queryDoc = new QueryDocument(query);
var result = collection.FindAs<TypeOfResultExpected>(queryDoc); // or just use Find

If it's something you plan on doing frequently, you could always wrap it in a method, or create a JSQueryDocument class like the following:

public class JSQueryDocument : QueryDocument
{
    public JSQueryDocument(string query) : base(MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>(query))
    {
        // Probably better to do this as a method rather than constructor as it
        // could be hard to debug queries that are not formatted correctly
    }
}

/// ...

var result = collection.Find(new JSQueryDocument("{ SendId: 4, 'Events.Code' : { $all : [2], $nin : [3] } }"));
Sign up to request clarification or add additional context in comments.

3 Comments

awesome! I totally missed that overload on QueryDocument because I didn't realize that BsonDocument implements IEnumerable<BsonElement>. Thanks!
BsonDocument.Parse() will be better ?!
But this will get a deserialization error if your string has a DateTime property "{update_time : " + DateTime.Now + " }"
13

To add to Shaun McCarthy's answer there's a slightly cleaner way to achieve the exact same goal using BsonDocument.Parse together with QueryDocument:

var json = "{ SendId: 4, 'Events.Code' : { $all : [2], $nin : [3] } }";
collection.Find(new QueryDocument(BsonDocument.Parse(json)));

7 Comments

Your answer may be shorter but it allows for fewer points of confirmation which an application layer may be dependent on to provide expected user experience or otherwise report errors.
@M.Babcock that's beside the point. The issue is that this answer uses BsonDocument.Parse which is the relevant API instead of MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument> which isn't really.
What is the namespace to include to be able to use the QueryDocument class ? I'm building an ASP vNext application and I can not find this class.
@Tareck117 Are you using the v2.x driver? You probably don't need that class. You can pass a BsonDocument or even just a string.
QueryDocument has been removed in MongoDB.Driver 2.5.0.0. is there another way to find from a query in json format?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.