Couchbase部分更新无法按预期工作

时间:2017-09-06 07:43:58

标签: javascript couchbase partial upsert java-client

我正在对couchbase文档进行部分更新,如下所示:

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

当所有upsert调用中的所有值都属于同一类型时,一切正常。

但是,如果某些值是字符串,并且其他值是布尔值,则我们得到例外:

  

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

在upsert的测试用例中,找不到任何更新多个属性的情况。

我们如何在Couchbase中使用不同类型的属性备份文档?

编辑#1:

现在,事情变得更奇怪......如果我在一次迭代中更新超过16个属性,我会得到相同的异常。

3 个答案:

答案 0 :(得分:1)

Couchbase Sub-Document API documentation(参见限制部分):

  

您不能在lookup-in或mutate-in命令中组合超过16个操作。

我猜你在两种情况下遇到了这种限制,混合值类型和单值类型。

使用Couchbase Java SDK 2.3.7版验证。

答案 1 :(得分:0)

现在,我们按类对属性进行分组,并执行与类型一样多的文档upsert。

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();            
}

这是一个效率低下的黑客。欢迎提供更好的解决方案。

答案 2 :(得分:0)

您可以一次合并16个操作中的多个操作,然后执行mutateInBuilder。这将减少操作次数。

        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();