2

I am doing partial update of a couchbase document as follows:

...
MutateInBuilder builder = bucket.mutateIn(id);
for (Map.Entry<String, Object> entry : map.entrySet())
{
    builder = builder.upsert(entry.getKey(), entry.getValue());
}
builder.execute();
...

When all the values in all the upsert calls are of the same type, things work fine.

However, if some values are strings, and say others are Boolean, we are getting the exception:

com.couchbase.client.core.CouchbaseException: SUBDOC_INVALID_COMBO at com.couchbase.client.java.subdoc.SubdocHelper.commonSubdocErrors(SubdocHelper.java:100) at com.couchbase.client.java.subdoc.AsyncMutateInBuilder$2.call(AsyncMutateInBuilder.java:1094) at com.couchbase.client.java.subdoc.AsyncMutateInBuilder$2.call(AsyncMutateInBuilder.java:1052)

In the testcases for upsert, could not find any case where multiple attributes are updated.

How do we upsert a document with attributes of different types in Couchbase?

EDIT#1:

Now, things got weirder... I am getting the same exception if I update more than 16 attributes in one iteration.

user3911119
  • 225
  • 2
  • 12

3 Answers3

1

From the Couchbase Sub-Document API documentation (see the Limits section):

You may not combine more than 16 operations within a lookup-in or mutate-in command.

I guess you were encountering this limitation in both cases, mixed value type and single value type.

Verified using Couchbase Java SDK version 2.3.7.

Jeff Kurtz
  • 631
  • 4
  • 8
0

For now, we have grouped attributes by class and executing as many document upserts as there are types.

for(Map.Entry<Class, Map<String, Object>> entry : attributesByClass.entrySet())
{
    MutateInBuilder builder = bucket.mutateIn(id);
    for (Map.Entry<String, Object> tmp : entry.getValue().entrySet())
    {
        builder = builder.upsert(tmp.getKey(), tmp.getValue());
    }
    builder.execute();            
}

It is an inefficient hack. A better solution is welcome.

user3911119
  • 225
  • 2
  • 12
0

You can club multiple of 16 operations at a time and execute mutateInBuilder. This will reduce the number of operations.

        MutateInBuilder mutateInBuilder = bucket.mutateIn(id);
        int valueCount = 1;

        for (Map.Entry<String, JsonElement> entry : valueEntries) {
            mutateInBuilder.upsert(entry.getKey(), entry.getValue().getAsString());
            if(valueCount % 16 == 0){ // Limitation of subdoc operations for jdk 2.7
                mutateInBuilder.execute();
                mutateInBuilder = bucket.mutateIn(id);
            }
            valueCount++;
        }

        mutateInBuilder.execute();
loknath
  • 718
  • 2
  • 8
  • 19