17

I have a product document that contains an array of documents. For example

{
 id: 1,
 name: "J-E-L-L-O",
 store:[{id: 1,
    name: "Store X"},
    {id: 2,
    name: "Store Y"}]
}

I would like to change the name of "Store Y" to Store Z", for instance. At the time, I don't know the index of the object. So, I pull the entire array, find the object to update, change the name, and then attempt to set the value of "store" with the updated array.

productCollection.Update(query, Update.Set("store", storeList.ToBsonDocument()));

However, I am getting an error: "An Array value cannot be written to the root level of a BSON document."

I think I just need to know how to serialize the array of custom objects to an array of BsonDocuments.

Thanks in advance for your help.

5 Answers 5

9

Unfortunately I had the same problem and ended up making an extension method to help me get around it.

    public static BsonArray ToBsonDocumentArray(this IEnumerable list)
    {
        var array = new BsonArray();
        foreach (var item in list)
        {
            array.Add(item.ToBson());
        }
        return array;
    }

so you should be able to do:

productCollection.Update(query, Update.Set("store", storeList.ToBsonDocumentArray()));
Sign up to request clarification or add additional context in comments.

3 Comments

When I use the extension method that u mentioned i get the below error like: A String value cannot be written to the root level of a BSON document. Any Ideas?
I guess this strictly applies to BsonArray type
@SunnySharma 6 years ago when I wrote that reply, it was quite specifically to the BsonArray type, yes. However I cannot answer for what the state of affairs with MongoDb may be today.
2

The exception says that you cannot convert an array/list into a BsonDocument. I think that you are looking to convert storeList to a [BsonArray][1].

If storeList is already an array of BsonDocument or some IEnumerable<T> where to can be converted to a BsonDocument, the you should not need to cast the storeList variable at all.

1 Comment

It's a Generic List of custom objects, so List<T>. Do I have to convert each element to a BsonDocument then put it in an array?
1

you should use

BsonDocument.Parse(storeList);

instead of

storeList.ToBsonDocument()

1 Comment

No, you cant use Parse since it is used on strings, not lists or other objects.
1

Little edit for the accepted answer function:

public static BsonArray ToBsonDocumentArray(this IEnumerable list)
    {
        var array = new BsonArray();
        foreach (var item in list)
        {
            array.Add(item);
        }
        return array;
    }

we don't need to convert item.ToBson(). There is already an implicit conversion from string to bson.Thats the reason i was getting an error message "A String value cannot be written to the root level of a BSON document."

1 Comment

for me it says - "cannot convert from "object" to "MongoDB.Bson.BsonValue" at line #6 (array.Add(item))!
0

One way to do this creating the class structure:

public class StoreBrand
{
    [BsonId]
    public int StoreCollectionId {get;set;} // 1
    public string Name {get;set;} // J-E-L-L-O
    public IEnumerable<Store> Stores {get;set;}
}

public class Store
{
    public int StoreId {get;set;} // 1, 2
    public string Name {get;set;} //Store X, Store Y
}


//generic way to insert into MongoDb
public class MongoDBService
{
    IMongoDatabase _database;
    public class MongoDBService(IMongoDatabase database)
    {
        _database = database;
    }
    public class Insert<T>(T entry)
    {
        //Change the collection name as needed
        string collectionName = typeof(T).Name;
        _database.GetCollection<T>(collectionName).InsertOne(entry);
    }    
}

public class Main //Your desired entry point
{
    var store = new Store(); //Create your list of stores
    var storeBrandObject = new StoreBrand(); //Insert list into Store Brand.

    var db = new MongoDbService(/*Inject your IMongoDatabase*/);
    db.Insert<StoreBrand>(storeBrandObject); //This will transform the data
}

Adjust as needed.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.