I have a hierarchical category document, like parent - Children - Children and so on....
{
id: 1,
value: {
}Children: [{
id: 2,
value: {
}Children: [{
id: 3,
value: {
}Children: [{
id: 4,
value: {
}Children: [{
id: 5,
value: {
}Children: [{
id: 6,
value: {
}Children: [{
id: 7,
value: {
}Children: []
}]
}]
}]
}]
}]
}]
}
In such documents, using MongoDB C# driver, how can I find a node where Id = x
I tried something like this
var filter = Builders<Type>.Filter.Eq(x => x.Id, 3);
var node = mongoDbRepository.GetOne(filter) ??
mongoDbRepository.GetOne(Builders<Type>.Filter.Where(x => x.Children.Any(c=>c.Id == 3)));
But this covers only two levels. In my example, I have 7 levels and I don't have a restriction on depth of level
Once I find that node I need to update that node.
MongoDB Documentation talks about hierarchical documents, but doesn't cover my scenario.
In your situation if you
don't have a restriction on depth of level
you can`t create update query. You must change schema for store data:
https://docs.mongodb.com/v3.2/tutorial/model-tree-structures/
If you depth is fixed:
public class TestEntity
{
public int Id { get; set; }
public TestEntity[] Value { get; set; }
}
class Program
{
static void Main()
{
const string connectionString = "mongodb://localhost:27017";
var client = new MongoClient(connectionString);
var db = client.GetDatabase("TestEntities");
var collection = db.GetCollection<TestEntity>("Entities");
collection.InsertOne(CreateTestEntity(1, CreateTestEntity(2, CreateTestEntity(3, CreateTestEntity(4)))));
const int selctedId = 3;
var update = Builders<TestEntity>.Update.AddToSet(x => x.Value, CreateTestEntity(9));
var depth1 = Builders<TestEntity>.Filter.Eq(x => x.Id, selctedId);
var depth2 = Builders<TestEntity>.Filter.Where(x => x.Value.Any(item => item.Id == selctedId));
var depth3 = Builders<TestEntity>.Filter.Where(x => x.Value.Any(item => item.Value.Any(item2 => item2.Id == selctedId)));
var filter = depth1 | depth2 | depth3;
collection.UpdateMany(filter, update);
// if you need update document on same depth that you match it in query (for example 3 as selctedId),
// you must make 2 query (bad approach, better way is change schema):
//var testEntity = collection.FindSync(filter).First();
//testEntity.Value[0].Value[0].Value = new[] {CreateTestEntity(9)}; //todo you must calculate depth what you need in C#
//collection.ReplaceOne(filter, testEntity);
}
private static TestEntity CreateTestEntity(int id, params TestEntity[] values)
{
return new TestEntity { Id = id, Value = values };
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With