RejectedSoftware Forums

Sign up

Bson: Modify array in Bson object

Suppose I found and object from collection,
auto b = coll.findOne(["id" : id]);

and b looks like:
{
id: "some_id",
array: ["element1", "element2"]
}

How should I append "element3" to the back of array,
and then save the object back into collection?

Thanks!

Re: Bson: Modify array in Bson object

On Mon, 27 Jan 2014 08:05:53 GMT, Kai-Heng Feng wrote:

Suppose I found and object from collection,
auto b = coll.findOne(["id" : id]);

and b looks like:
{
id: "some_id",
array: ["element1", "element2"]
}

How should I append "element3" to the back of array,
and then save the object back into collection?

Thanks!

You currently have to convert to an array, perform the modifications and write back to Bson:

auto b = coll.findOne(["id": id]);
auto list = b.array.get!(Bson[]);
list ~= Bson("some_elem");
b.array = Bson(list);
coll.update(["id": id], b);

But usually the most efficient and least error prone approach is to define a struct matching the DB entry and use serialization:

struct DBEntry { BsonObjectID _id; string[] array; }
auto e = deserializeBson!DBEntry(coll.findOne(["id": id]));
e.array ~= "some_elem";
coll.update(["id": id], e);

Of course, for specific cases it is better to use the matching MongoDB expressions. In this case:

coll.update(["id": id], ["$push": ["array": "some_elem"]]);

The reason why Bson doesn't define a lot of operations that would theoretically be possible, is that their implementation cannot be efficient due to the way Bson is layed out in memory. The idea is to force using more efficient patterns for modifying data and keeping Bson mostly as a pure storage/transfer format.

Re: Bson: Modify array in Bson object

On Mon, 27 Jan 2014 14:44:57 GMT, Sönke Ludwig wrote:

On Mon, 27 Jan 2014 08:05:53 GMT, Kai-Heng Feng wrote:

Suppose I found and object from collection,
auto b = coll.findOne(["id" : id]);

and b looks like:
{
id: "some_id",
array: ["element1", "element2"]
}

How should I append "element3" to the back of array,
and then save the object back into collection?

Thanks!

You currently have to convert to an array, perform the modifications and write back to Bson:

auto b = coll.findOne(["id": id]);
auto list = b.array.get!(Bson[]);
list ~= Bson("some_elem");
b.array = Bson(list);
coll.update(["id": id], b);

But usually the most efficient and least error prone approach is to define a struct matching the DB entry and use serialization:

struct DBEntry { BsonObjectID _id; string[] array; }
auto e = deserializeBson!DBEntry(coll.findOne(["id": id]));
e.array ~= "some_elem";
coll.update(["id": id], e);

Of course, for specific cases it is better to use the matching MongoDB expressions. In this case:

coll.update(["id": id], ["$push": ["array": "some_elem"]]);

The reason why Bson doesn't define a lot of operations that would theoretically be possible, is that their implementation cannot be efficient due to the way Bson is layed out in memory. The idea is to force using more efficient patterns for modifying data and keeping Bson mostly as a pure storage/transfer format.

Thanks for your reply,
That's exactly I'm looking for!

Is BsonObjectID _id in struct definition mandatory?
Or more generally, does user-defined struct needs to have fields that one-to-one map to MongoDB Bson structure?

Thanks!