如何使用spring mongo data api更新嵌入式mongo文档

时间:2014-04-03 12:19:08

标签: java spring mongodb mongodb-query

    I need some help updating property of embedded collection with JSON structure below       -
     translation
    {
     "_id" : ObjectId("533d4c73d86b8977fda970a9"),
     "_class" : "com.xxx.xxx.translation.domain.Translation",
     "locales" : [ 
       {
        "_id" : "en-US",
        "description" : "English (United States)",
        "isActive" : true
       }, 
      {
        "_id" : "pt-BR",
        "description" : "Portuguese (Brazil)",
        "isActive" : true
      }, 
     {
        "_id" : "nl-NL",
        "description" : "Dutch (Netherlands)",
        "isActive" : true
     }
     ],
     "screens" : [ 
     {
        "_id" : "caseCodes",
        "dictionary" : [ 
            {
                "key" : "CS_CAT1",
                "parameterizedValue" : "My investigations",
                "locale" : "en-US"
            }, 
            {
                "key" : "MY_INVESTIGATIONS",
                "parameterizedValue" : "",
                "locale" : "pt-BR"
            }, 
       }
      ]
     }

在上述结构中: 我想更新" parameterizedValue"使用spring-data-mongo-db API 1.3.4,用于_id =" caseCodes"和key =" CS_CAT1"。

我试过了(这里'值'是TranslationValue数组的集合名称)

      mongoOperations.updateFirst(Query.query(Criteria.where("screens._id")
            .is("caseCodes")), new Update().push(
            "screens.dictionary.$.values", translationValue),
            Translation.class);

但它说,"不能将数组附加到字符串"字典" ....

这里有任何指示或帮助吗?感谢。

-Sanjeev

1 个答案:

答案 0 :(得分:3)

您的逻辑存在一些问题以及此类更新的架构问题。

首先,您拥有的是嵌套数组,这会导致更新问题,如positional $运算符的文档中所述。这意味着,在update语句的查询端匹配数组元素的任何条件都匹配找到的第一个数组索引。

由于您需要在内部数组中使用特定条目,因此您也需要匹配它。但是"赶上"说只有第一个匹配才会在位置运算符中使用,所以你不能同时使用这两个匹配。查询表单(如果它可以工作,它没有)将实际上是这样的(本机shell):

db.collection.update(
    { 
        "screens._id": "caseCodes",
        "screens.dictionary.key": "CS_CAT1"
    },
    {
        "$set": { 
            "screens.$.dictionary.$.parameterizedValue": "new value"
        }
    }
)

现在,这将出现"要比你正在做的更正确,但当然这会失败,因为位置操作符不能多次使用。在这种情况下,我可能只是非常愚蠢地工作,因为它发生了"屏幕的第一个匹配的索引" array(为0)恰好与内部元素的必需索引完全相同。但实际上这只是运气不好而且#34;。

为了更好地说明,您需要对这些类型的更新执行了解元素的索引,并使用"点符号&#34将这些值直接放入更新语句中;。所以更新你的第二个字典"元素会是这样的:

db.collection.update(
    { 
        "screens._id": "caseCodes",
        "screens.dictionary.key": "MY_INVESTIGATIONS"
    },
    {
        "$set": { 
            "screens.0.dictionary.1.parameterizedValue": "new value"
        }
    }
)

另请注意,此处使用的正确运算符为$set,因为您没有附加到任何一个数组,而是希望更改元素。

由于更新中的那种准确性不太适合您的需要,因此您应该考虑更改架构以更加支持的方式来适应您的操作。所以有一种可能性就是你的屏幕"数据可能不一定是数组,您可以将其更改为文档形式:

     "screens" : {
         "caseCodes": [ 
             {
                 "key" : "CS_CAT1",
                 "parameterizedValue" : "My investigations",
                 "locale" : "en-US"
             }, 
             {
                 "key" : "MY_INVESTIGATIONS",
                 "parameterizedValue" : "",
                 "locale" : "pt-BR"
             }, 
         ]
     }

这将表格改为:

db.collection.update(
    { 
        "screens.caseCodes.key": "CS_CAT1"
    },
    {
        "$set": { 
            "screens.caseCodes.$.parameterizedValue": "new value"
        }
    }
)

这可能适用于您的目的,也可能不适用,但您要么受限于使用嵌套数组,要么以某种方式更改您的架构。