I need to map to a simplified document some documents in a collection.
I can obtain what I need with this in the mongo shell:
db.getCollection('items').aggregate([
{ "$project": {
"Team": "$TeamId",
"Marker": "$Properties.marker.Value"
}}
])
I need to obtain the same result with C# driver (version 2.3.0); I tried this
var aggregation = m_database.GetCollection<BsonDocument>("items").Aggregate();
var projectionDefinition = new BsonDocument("$project", new BsonDocument
{
{ "Team", "$TeamId"},
{ "Marker", "$Properties.marker.Value" }
});
var query = aggregation.Project(projectionDefinition);
var result = await query.ToListAsync();
but I get the following error
Command aggregate failed: $expressions are not allowed at the top-level of $project
Someone kwons what's going on?
if you call Project you do have already $project in your bson,
so you just simplify your projectionDefinition:
var projectionDefinition = new BsonDocument
{
{ "Team", "$TeamId"},
{ "Marker", "$Properties.marker.Value" }
};
My personal opinion: I would avoid using pure bson, MongoDB driver gives you possibilities to use your c# dto classes for it.
Related
Hi everybody in a previous post ( ListCollections with autorizedcollection ) I asked how to retrieve the name of the collections available in MongoDb'database. Finally the solution is much easier as expected and is :
var db = mongoUser.GetDatabase(databaseName);
var command = new CommandDocument { { "listCollections", 1 }, { "authorizedCollections", true }, {"nameOnly", true }};
var result = db.RunCommand<BsonDocument>(command);
the problem is I am not used to work with BsonDocument. I could cast the "result" into a BsonDocument or onto a string and then cut until I found the name of the solution. But it is the wrong way. Could someone help me for this case ?
you should not use CommandDocument since it's a Legacy API and you use not legacy code path in all other places. I think BsonDocument is the expected way to work with RunCommand. You can play with the above Deserialization suggestions but this will be just a step after RunCommand.
So I would expect something like this:
var command = new BsonDocument { { "listCollections", 1 }, { "authorizedCollections", true }, { "nameOnly", true } };
var result = db.RunCommand<BsonDocument>(command);
// any steps you want to process result including possible deserialization into typed view
Below is the sample Bson document which is unstructured. As I am new to MongoDB try to learn building queries.
{
"_id":ObjectId("562e7c594c12942f08fe4192"),
"shapes":[
{
"shape":"square",
"color":"blue"
},
{
"shape":"circle",
"color":"red"
}
]
},
{
"_id":ObjectId("562e7c594c12942f08fe4193"),
"shapes":[
{
"shape":"square",
"color":"black"
},
{
"shape":
{
"shape_s_time":""2020-06-29T12:00:14.3716902Z"
"shape__time":""2020-06-29T12:00:16.3716902Z"
},
"color":"green"
}
]
}
I have tried this code
var collection= db.GetCollection<BsonDocument>("Test");
var result = collection.Find(new BsonDocument()).Project(Builders<BsonDocument>.Projection.Include("shapes.shape.shape_s_time")).ToList();
but it giving error as
Could someone tell how to get values?
you have problems with data. The two above document examples works without any issues. It looks like some of your documents here shapes.shape.shape_s_time have different format
I am using MongoDB C# driver version 2.2. My collection contains "Parent" objects. Each parent object has an array of children objects. Each child has name value:
"parent": {
"children":[
{ "name": "Bob", "age": 10},
{ "name": "Alice", "age": 7},
{ "name": "Tobias", "age": 11}
]
}
I need to translate the following code into C# statements / LINQ syntax:
db.getCollection('Parents').find({'parent.children': { $elemMatch: { 'name': { $regex: '.*ob.*', $options: 'im' } }}})
I have found there are methods like
var builder = Builders<BsonDocument>.Filter;
builder.Regex("parent.children.name", new BsonRegularExpression(".*ob.*")); //does not work with array
and
builder.AnyEq("parent.children.name", "ob"); //without regex
But I cannot understand how to combine them. Please advise.
UPDATE:
I am using the following for now, please correct me if you know a reason why it should not work correctly:
builder.AnyEq("parent.children.name", new BsonRegularExpression(".*ob.*"))
I am using the following for now:
builder.AnyEq("parent.children.name", new BsonRegularExpression(".*ob.*"))
Can't test C# on this machine. Let me know if this doesn't work:
var filter = Builders<People>.Filter.ElemMatch(x => x.Parent.Children, x => Regex.IsMatch(x.Name, "regex"));
var res = await collection.Find(filter).ToListAsync();
Here's a trick you might like btw:
// Take your inputted `find` query string:
string bsonQuery = "{'parent.children': { $elemMatch: { 'name': { $regex: '.*ob.*', $options: 'im' } }}}";
// Use it as the filter!
var filter = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>(bsonQuery);
// Results:
var result = col.FindSync (filter).ToList();
I've tested your current expression (builder.AnyEq("parent.children.name", new BsonRegularExpression(".*ob.*")) on a database at home and I don't believe it behaves in the way you intend.
Although the c# documentation doesn't explicitly state this, mongoDB supports the Regex filter on an array field. I have tested the below expression in C# and have correct results for the Regex despite the field being an array.
builder.Regex(MONGO_FIELD_NAME, new BsonRegularExpression("SOME REGEX"));
In addition, I've tested Regex on the toy example in the [online mongo webshell for query arrays] (https://docs.mongodb.com/manual/tutorial/query-arrays/). Querying for db.inventory.find({tags : {$regex : "^bl"}} will return results with "blank" or "blue" despite the "tag" field being an array.
I have many complex queries that I sometimes wish to check directly against Mongo for debugging \ explaining() purposes.
With the newer 2.0+ c# driver, i'm not sure how to do this. With the previous version there was a thing called IMongoQuery and This worked.
A simple example:
FilterDefinition<LalalaEvent> filter = Builders<LalalaEvent>.Filter
.Where(e => ids.Contains(e.Id) && e.Deleted != true );
I was trying to solve the same problem today. Here is what I found.
public static class MongoExtensions
{
public static BsonDocument RenderToBsonDocument<T>(this FilterDefinition<T> filter)
{
var serializerRegistry = BsonSerializer.SerializerRegistry;
var documentSerializer = serializerRegistry.GetSerializer<T>();
return filter.Render(documentSerializer, serializerRegistry);
}
}
I didn't have access to a collection when I was calling it, so I couldn't use the above solutions.
This allows you to do
var json = filter.RenderToBsonDocument().ToJson();
If you're using the latest version of the driver, which is 2.0.1 you can easily put that filter in a Find operation, get back an IFindFluent and print its ToString:
var filter = Builders<LalalaEvent>.Filter.Where(e => ids.Contains(e.Id) && e.Deleted != true);
var findFluent = collection.Find(filter);
Console.WriteLine(findFluent);
For example for me this prints:
find({ "_id" : { "$in" : [1, 2, 3] }, "Deleted" : { "$ne" : true } })
You are able to perform that using the collection's properties:
var result = filter.Render(collection.DocumentSerializer,
collection.Settings.SerializerRegistry).ToString();
This is my code... but runcommand doesn't get any results
Notice : "title" is an indexed field
var mongoClient = new MongoClient(ConfigurationManager.AppSettings["connectionString"]);
var server = mongoClient.GetServer();
mongodatabase = server.GetDatabase("Htmlattachment2");
MongoCollection<Department> attachments = mongodatabase.GetCollection<Department>("attachment2");
attachments.EnsureIndex(new IndexKeysBuilder().Ascending("title"));
attachments.Insert(new BsonDocument("title", "The quick brown fox"));
var t = attachments.GetIndexes().ToList();
//foreach (Attachements emp in attachments.FindAll())
//{ }
var textSearchCommand = new CommandDocument
{
{ "text","title" },
{ "search", textBox1.Text }
};
var commandResult = mongodatabase.RunCommand(textSearchCommand);
var response = commandResult.Response["results"].AsBsonArray;
foreach (BsonDocument result in response)
{
// process result
}
It might be easier if you just used LINQ to perform queries. There is a tutorial on how use LINQ with MongoDB here. Note that the MongoDB C# driver translates the LINQ queries to run on the database as native Mongo queries.