In MongoDB 3.0 with the C# 2.0 driver, how do you get a distinct list of values using DistinctAsync from a document's array of sub documents?
I'm looking for the C# equivalent of this in the shell:
db.cars.distinct("parts.name", {"make":"Ford"})
After admitting defeat, I resorted to this shell-ish code:
var distinctParts = await db.RunCommandAsync<BsonDocument>(new BsonDocument {
{ "distinct", "cars"},
{"key", "parts.name"},
{"query", new BsonDocument { { "make", "Ford" }} } });
Thanks!
Something like this should work:
var filter = new MongoDB.Driver.ExpressionFilterDefinition<CARS_TYPE>(x => x.make == "ford");
var distinctParts = await cars_collection.DistinctAsync<string>("parts.name", filter);
Related
I have this query which works fine in datagrip
test> db.getCollection("comments").find({status: {$ne: "APPROVED"},storyID: {$regex: "bbjfn-*"}})
I'm just wondering how to achieve the same thing in C# using the MongoDB Driver 2.13.1
IMongoDatabase database = MongoClient.GetDatabase(Program.Settings.MongoDB.Database);
IMongoCollection<BsonDocument> collection = database.GetCollection<BsonDocument>("comments");
var filter = Builders<BsonDocument>.Filter.Eq("status", new BsonDocument("$ne", "APPROVED")) &
Builders<BsonDocument>.Filter.Eq("storyID", new BsonDocument("$regex", "bbjfnfn-*"));
var results = await collection.FindAsync(filter);
Doesn't work.. what am I doing wrong?
You can set filter with BsonDocument object as below:
FilterDefinition<Store> filter = new BsonDocument
{
{ "status", new BsonDocument("$ne", "APPROVED") },
{ "storyID", new BsonDocument("$regex", "bbjfn-*") }
};
OR
var builder = Builders<BsonDocument>.Filter;
var filter = builder.Ne("status", "APPROVED") & builder.Regex("storyID", "bbjfn-*");
FYI, you can use MongoDB Compass to export Query to C# Language.
Mongo DB's Aggregation pipeline has an "AddFields" stage that allows you to project new fields to the pipeline's output document without knowing what fields already existed.
It seems this has not been included in the C# driver for Mongo DB (using version 2.7).
Does anyone know if there are any alternatives to this? Maybe a flag on the "Project" stage?
I'm not sure all the BsonDocument usage is required. Certainly not in this example where I append the textScore of a text search to the search result.
private IAggregateFluent<ProductTypeSearchResult> CreateSearchQuery(string query)
{
FilterDefinition<ProductType> filter = Builders<ProductType>.Filter.Text(query);
return _collection
.Aggregate()
.Match(filter)
.AppendStage<ProductType>("{$addFields: {score: {$meta:'textScore'}}}")
.Sort(Sort)
.Project(pt => new ProductTypeSearchResult
{
Description = pt.ExternalProductTypeDescription,
Id = pt.Id,
Name = pt.Name,
ProductFamilyId = pt.ProductFamilyId,
Url = !string.IsNullOrEmpty(pt.ShopUrl) ? pt.ShopUrl : pt.TypeUrl,
Score = pt.Score
});
}
Note that ProductType does have a Score property defined as
[BsonIgnoreIfNull]
public double Score { get; set; }
It's unfortunate that $addFields is not directly supported and we have to resort to "magic strings"
As discussed here Using $addFields in MongoDB Driver for C# you can build the aggregation stage yourself with a BsonDocument.
To use the example from https://docs.mongodb.com/manual/reference/operator/aggregation/addFields/
{
$addFields: {
totalHomework: { $sum: "$homework" } ,
totalQuiz: { $sum: "$quiz" }
}
}
would look something like this:
BsonDocument expression = new BsonDocument(new List<BsonElement>() {
new BsonElement("totalHomeWork", new BsonDocument(new BsonElement("$sum", "$homework"))),
new BsonElement("totalQuiz", new BsonDocument(new BsonElement("$sum", "$quiz")))
});
BsonDocument addFieldsStage = new BsonDocument(new BsonElement("$addFields", expression));
IAggregateFluent<BsonDocument> aggregate = col.Aggregate().AppendStage(addFieldsStage);
expression being the BsonDocument representing
{
totalHomework: { $sum: "$homework" } ,
totalQuiz: { $sum: "$quiz" }
}
You can append additional stages onto the IAggregateFluent Object as normal
IAggregateFluent<BsonDocument> aggregate = col.Aggregate()
.Match(filterDefintion)
.AppendStage(addFieldsStage)
.Project(projectionDefintion);
I have documents:
{"handler":"north"}
{"handler":"south"}
{"handler":"west"}
{"handler":"east"}
I want to find a matching handler from a given string input, e.g. "westtown" and expects the handler will be "west".
Please help, my code below does not work.
String inputstring = "westtown";
IMongoCollection<BsonDocument> collection = null;
List<BsonDocument> pages = null;
try
{
collection = db.GetCollection<BsonDocument>("handlers");
pages = await collection.Find(x => (inputstring.StartsWith(x["handler"].AsString))).ToListAsync<BsonDocument>();
}
...
I use classless scheme, so I use BsonDocument on the dynamic.
AFAIK, In MongoDB you can find it with $where operator like this:
{ $where: "'westtown'.startsWith(this.handler)" }
So, I think in c# you can do it with something like this:
var filter =
new BsonDocument(
new Dictionary<string, BsonValue>
{
{
"$where",
new BsonString("'westtown'.startsWith(this.handler)")
}
});
var result = col.Find(filter).ToList();
Per title - I am using the official mongodb driver and I am looking to get all POIs within the given bounding box.
So far I have:
MongoCollection<BsonDocument> collection = _MongoDatabase.GetCollection("pois");
BsonArray lowerLeftDoc = new BsonArray(new[] { lowerLeft.Lon, lowerLeft.Lat});
BsonArray upperRightDoc = new BsonArray(new[] { upperRight.Lon, upperRight.Lat});
BsonDocument locDoc = new BsonDocument
{
{ "$within", new BsonArray(new[] { lowerLeftDoc, upperRightDoc})}
};
BsonDocument queryDoc = new BsonDocument { { "loc", locDoc }};
IList<TrafficUpdate> updates = new List<TrafficUpdate>();
var results = collection.Find(new QueryDocument(queryDoc)).SetLimit(limit);
foreach (BsonDocument t in results)
{
}
Unfortunatelly this doesnt work. I get:
QueryFailure flag was unknown $within type: 0 (response was { "$err" :
"unknown $within type: 0", "code" : 13058 }).
The problem in your code is that you didnt specify which geo operation you wanted to use. You only specified $within but missed where. you must specify $within along with $box (bounding box) , $polygon , $center or $centerSphere / $nearSphere.
This is the correct mongo syntax to run $box queries
> box = [[40.73083, -73.99756], [40.741404, -73.988135]]
> db.places.find({"loc" : {"$within" : {"$box" : box}}})
i am not sure about the c# mongodb syntax. But if you include '$box', it ll work
You could also use the Query builder for this query:
var query = Query.Within("loc", lowerLeft.Lon, lowerLeft.Lat,
upperRight.Lon, upperRight.Lat);
and let the query builder worry about the nitty gritty details of creating a properly formed query.
How to search document by range with MongoDB driver for C#?
usual query in mongo is something like :
db.collection.find({ "field" : { $gt: value1, $lt: value2 } } );
But how to do same with C# driver for mongoDb?
var collection = Database.GetCollection<Type>("collection");
var mongoQuery = Query.GT("field", value1).LT(value2);
var list = collection.Find(mongoQuery);