2012-05-11 1 views
3

Я пытаюсь вставить вложенные документы в MongoDB с помощью C#. У меня есть коллекция под названием категории. В этой коллекции должны быть документы с 2 массивами, одна из названных категорий и один именованный стандарт. Внутри этих массивов должны существовать новые документы со своими собственными идентификаторами, которые также содержат массивы с теми же именами, что указаны выше. Ниже приводится то, что у меня есть до сих пор, но я не уверен, как действовать дальше. Если вы посмотрите на код, что я хочу сделать, это добавить документ «namingConventions», вложенный в массив категорий в документе категорий, однако имена именования должны иметь уникальный идентификатор.Вложенная вставка документа в MongoDB с C#

На этом этапе я не уверен, что я сделал это как можно лучше, поэтому я открыт для всех и всяких советов по всему этому.

namespace ClassLibrary1 
{ 
using MongoDB.Bson; 
using MongoDB.Driver; 
public class Class1 
{ 
     public void test() 
     { 
      string connectionString = "mongodb://localhost"; 
      MongoServer server = MongoServer.Create(connectionString); 
      MongoDatabase standards = server.GetDatabase("Standards"); 
      MongoCollection<BsonDocument> categories = standards.GetCollection<BsonDocument>("catagories"); 

      BsonDocument[] batch = { 
             new BsonDocument { { "categories", new BsonArray {} }, 
                 { "standards", new BsonArray { } } }, 
             new BsonDocument { { "catagories", new BsonArray { } }, 
                 { "standards", new BsonArray { } } }, 
            }; 
      categories.InsertBatch(batch); 

      ((BsonArray)batch[0]["categories"]).Add(batch[1]); 
      categories.Save(batch[0]);   
     } 
    } 
} 

Для ясности это то, что мне нужно:

Что я делаю это создание сайта стандартов кодирования. Компания хочет, чтобы все стандарты хранились в MongoDB в дереве. Все должно иметь уникальный идентификатор, чтобы, помимо того, что он был запрошен как дерево, он также может быть запрошен сам по себе. Примером может быть:

/* 0 */ 
{ 
    "_id" : ObjectId("4fb39795b74861183c713807"), 
    "catagories" : [], 
    "standards" : [] 
} 

/* 1 */ 
{ 
    "_id" : ObjectId("4fb39795b74861183c713806"), 
    "categories" : [{ 
     "_id" : ObjectId("4fb39795b74861183c713807"), 
     "catagories" : [], 
     "standards" : [] 
    }], 
    "standards" : [] 
} 

Теперь я написал код, чтобы это произошло, но этот вопрос, кажется, что, когда я добавить объект «0» в категории массива в объекте «1» он не делает ссылку а вместо этого копировать его. Это не произойдет, потому что, если будут внесены изменения, они будут сделаны в исходный объект «0», поэтому они не будут нажаты на копию, создаваемую в массиве категорий, по крайней мере, это то, что происходит со мной. Надеюсь, это прояснит то, что я ищу.

+0

Какой драйвер вы используете? Кажется, что вы не используете официальный драйвер поддержки 10gen. Любая причина? –

+0

Является ли документ документа «0» намеренно таким же, как идентификатор первой категории документов «1»? –

+0

Я вижу сейчас. Это никогда не произойдет автоматически. Копия - единственный способ добиться такого поведения в MongoDB. Честно говоря, такое поведение никогда не будет происходить автоматически и в базе данных. Есть ли причина, по которой вам это нужно, чтобы быть таким? Эта схема для меня не имеет смысла. –

ответ

6

Так, на основе вашего последнего комментария, кажется, что это фактическая структура вы ищете:

{ 
    _id: ObjectId(), 

    name: "NamingConventions", 

    categories: [ 
     { 
      id: ObjectId(), 
      name: "Namespaces", 
      standards: [ 
       { 
        id: ObjectId(), 
        name: "TitleCased", 
        description: "Namespaces must be Title Cased." 
       }, 
       { 
        id: ObjectId(). 
        name: "NoAbbreviations", 
        description: "Namespaces must not use abbreviations." 
       } 
      ] 
     }, 
     { 
      id: ObjectId(), 
      name: "Variables", 
      standards: [ 
       { 
        id: ObjectId(), 
        name: "CamelCased", 
        description: "variables must be camel cased." 
       } 
      ] 
     } 
    ] 
} 

Предполагая, что это правильно, то ниже, как вы вставили бы один из них:

var collection = db.GetCollection("some collection name"); 

var root = new BsonDocument(); 
root.Add("name", "NamingConventions"); 
var rootCategories = new BsonArray(); 
rootCategories.Add(new BsonDocument 
{ 
    { "id": ObjectId.GenerateNewId() }, 
    { "name", "Namespaces" }, 
    { "standards", new BsonArray() } 
}); 

root.Add("categories", rootCategories); 
//etc... 
collection.Save(root); 

Надеюсь, что поможет, если нет, я сдаюсь :).

+0

. Это именно то, чего я хочу достичь, но код, который вы опубликовали, не делает этого. Я внес изменения, чтобы выполнить его, но он дает мне 2 документа без каких-либо ссылок. –

+0

обновил образец, чтобы быть более тщательным. Вы должны добавить поля в документ, чтобы они сохранялись. –

+0

Это сделало это! Спасибо тонну за то, что она прилипла к мне. Единственное, что мне нужно было сделать, это немного изменить код. {"id": ObjectId.NewObjectId()} не работает, он должен быть {"_id", ObjectId.GenerateNewId()} –

0

Итак, я думаю, я смущен тем, что вы просите. Если вы просто хотите хранить документы namingConventions внутри массива, вам не нужна коллекция для них. Вместо этого просто добавьте их в массив bson и сохраните их.

var categoriesCollection = db.GetCollection<BsonDocument>("categories"); 

var category = new BsonDocument(); 
var namingConventions = new BsonArray(); 
namingConventions.Add(new BsonDocument("convention1", "value")); 

category.Add("naming_conventions", namingConventions); 

categoriesCollection.Insert(category); 

Это создаст новый документ для категории, создать массив в нем называется naming_conventions с одним документом в нем с элементом под названием «конвенции1» и значение «значение».

+0

Посмотреть мое сообщение Я сделал другое редактирование –

+0

Я вижу это, но как вышесказанное не отвечает на ваш вопрос? Что касается уникального идентификатора, просто используйте Guid и когда вы создаете документ, присвойте ему поле id значение с помощью Guid.New(). –

+0

, потому что это не создает ссылку на документ в массиве. Если я вношу изменения в документ, массив останется прежним, не говоря уже о том, что нет идентификаторов. Что касается использования Guid.New(), вам нужно быть более конкретным. У меня нет идеи, о чем вы говорите. –

0

Я также не совсем уверен, чего вы пытаетесь достичь. Возможно, если вы разместите некоторые образцы документов в формате JSON, мы сможем показать вам код C# для записи документов, соответствующих этому.

В качестве альтернативы, если вы хотите обсудить свою схему, которая также может быть лучше выполнена в контексте JSON, а не C#, и как только схема будет решена, мы можем обсудить, как писать документы на эту схему в C# ,

Одна вещь, которая не звучит правильно в вашем первоначальном описании, была заявлением «в этой коллекции должно быть 2 массива». Коллекция может содержать только документы, а не массивы. Сами документы могут содержать массивы, если хотите.

+0

Извините, что я имел в виду документ, вот что мне нужно в JSON: см. Исходное сообщение для редактирования –

0
var filter = Builders<CollectionDefination>.Filter.Where(r => r._id== id); 
var data = Builders<CollectionDefination>.Update.Push(f=> 
    f.categories,categoriesObject); 
await _dbService.collection.UpdateOneAsync(filter,data); 

Примечание: убедитесь, что тип встроенного документа [Категории] - это массив.