I'm new to MongoDB so this might be a naive question, yet I have not found any relevant/up to date information by googling around: I am trying to use the MongoDB C# driver (version 2.2.4) to compose a LINQ-based query, one piece at a time, from a received filter
POCO object, like this:
IQueryable<BsonDocument> parts = collection.AsQueryable();
if (filter.Name != null)
parts = parts.Where(d => d["Name"].Equals(filter.Name));
// ... etc; I'll then call ToList() to get results ...
Now, one of my filter
properties is a string array, meaning that I should match any document whose field Vendor
(a string property in the MongoDB document) is equal to any of the strings in the array (like MongoDB native $in
: https://docs.mongodb.com/manual/reference/operator/query/in/).
To this end, I tried with Contains
(the special case for a 1-sized array is just an optimization):
if (filter.Vendors != null && filter.Vendors.Length > 0)
{
parts = filter.Vendors.Length == 1
? parts.Where(d => d["Vendor"].Equals(filter.Vendors[0]))
: parts.Where(d => filter.Vendors.Contains(d["Vendor"].AsString));
}
This compiles, but throws an ArgumentException
: "Expression of type 'MongoDB.Bson.BsonValue' cannot be used for parameter of type 'System.String' of method 'Boolean Contains[String](System.Collections.Generic.IEnumerable`1[System.String], System.String)'".
Looking at http://mongodb.github.io/mongo-csharp-driver/2.2/reference/driver/crud/linq/, there is nothing about Contains
or $in
; yet, from https://jira.mongodb.org/browse/CSHARP-462
it seems that the driver should now be capable of handling that method.
BTW, the same happens if I slightly change the code to:
parts.Where(d => filter.Vendors.Any(s=> d["Vendor"].Equals(s)));
which does not involve Contains
at all. The exception message complains about not being able to use BsonValue
for string
, yet that BsonValue
is right a string
. Could anyone suggest a solution?
The exception messages dance around the idea of fully embracing BsonValue
to let mongo handle the types instead of trying to cast to string
. I got it to work having Vendors as type List<BsonValue>
.
class Filter
{
public List<BsonValue> Vendors { get; set; }
}
...
var list = parts.Where(d => filter.Vendors.Contains(d["Vendor"]));
foreach (var document in list)
{
Console.WriteLine(document["Name"]);
}
Another alternative is to map your documents to a C# class instead of using BsonDocument as the collection type.
class MyDocument
{
public ObjectId Id { get; set; }
public string Name { get; set; }
public string Vendor { get; set; }
}
...
var collection = db.GetCollection <MyDocument> ("parts");