Protobuf: MergeFrom: add option to replace instead of append repeated fields

Created on 17 May 2017  Â·  5Comments  Â·  Source: protocolbuffers/protobuf

could we have an option in MergeFrom to replace instead of append repeated fields? It's a more natural behavior.
It would occur when the 2nd message contains elements of that repeated field.

Most helpful comment

A lot of people are using Protobuf to represent arbitrary large data sets (though I know this isn't its original purpose). It is very common to want to change the data with some kind of small delta instead of re-transmitting the entire large data set. For example, using Protobuf for a configuration file that's shared on client or server and wanting to modify the configuration for an A/B test. Or using Protobuf to store a user's data on client and server. In these cases, we take the server version, create a "delta" version of the message, merge the delta into the server version, then send the "delta" to the client and merge that there. We've now modified client and server data without sending the whole data. But in this delta case, the "mergeFrom" appends repeated fields which is far from the desired behavior. Replacing the repeated field works as long as the delta includes the entire repeated array. Ideally, the arrays would smart merge (if the original has elements 1-9 the other 1-7, then 1-7 would be replaced and 8-9 would remain).

Anyway, I understand that this use case is not the original intent of Protobuf, but patterns like this are used a lot which is why people keep requesting it.

All 5 comments

What language are you referring to?
On Wed, May 17, 2017 at 14:06 Timothee Cour notifications@github.com
wrote:

could we have an option in MergeFrom to replace instead of append repeated
fields? It's a more natural behavior.
It would occur when the 2nd message contains elements of that repeated
field.

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/google/protobuf/issues/3106, or mute the thread
https://github.com/notifications/unsubscribe-auth/AE9H5d6Nj8SYww5Kc55z3ZSTkUX-BXMQks5r62FMgaJpZM4NecEl
.

for example C++ protobuf apis.

message A{
  repeated string b=1;
}

I'd like:

A a1;
*a1.mutable_b()->add()="foo";

A a2;
*a2.mutable_b()->add()="bar1";
*a2.mutable_b()->add()="bar2";

// new optinonal flag I'd like (should default to true which is current logic)
bool is_append=false;
a1.MergeFrom(a2, is_append);
assert(a1.b().size() == 2);

@timotheecour We would probably be hesitant to implement this feature, because usually we don't want to take on the maintenance commitment of a new option unless there's a pretty compelling reason for it. What's your use case for this behavior? Note that the current behavior does make sense when you consider that it's consistent with MergeFromCodedStream and MergePartialFromCodedStream--when we're parsing we want new repeated field elements to be appended and so it makes some sense that MergeFrom does the same.

It's unlikely that we will ever introduce such an option to generated MergeFrom API. You can though implement the merging behavior using proto reflection API. You can take a look at FieldMaskUtil which has an example MergeFrom() implementation that allows you to replace repeated fields rather than appending.

A lot of people are using Protobuf to represent arbitrary large data sets (though I know this isn't its original purpose). It is very common to want to change the data with some kind of small delta instead of re-transmitting the entire large data set. For example, using Protobuf for a configuration file that's shared on client or server and wanting to modify the configuration for an A/B test. Or using Protobuf to store a user's data on client and server. In these cases, we take the server version, create a "delta" version of the message, merge the delta into the server version, then send the "delta" to the client and merge that there. We've now modified client and server data without sending the whole data. But in this delta case, the "mergeFrom" appends repeated fields which is far from the desired behavior. Replacing the repeated field works as long as the delta includes the entire repeated array. Ideally, the arrays would smart merge (if the original has elements 1-9 the other 1-7, then 1-7 would be replaced and 8-9 would remain).

Anyway, I understand that this use case is not the original intent of Protobuf, but patterns like this are used a lot which is why people keep requesting it.

Was this page helpful?
0 / 5 - 0 ratings