更新Mongodb中的多嵌套数组

时间:2013-04-14 19:18:35

标签: mongodb

我在Mongodb中有一个文档架构,如下所示:

{
    _id: 1
    tags: [{
        tag: 'foo'
        links: [{
            link: 'http:www.google.com'
            date: '123'
        }] 
    }]
}

我正在尝试将链接推送到文档中唯一的'links'数组。

我的第一个询问......

db.userlinks.update (
    {_id: 1, tags: {$nin: [{tag:'foo'}]}}, 
    {$push: {'tags': {tag:'foo'}}}, 
    {upsert: true}
)

给我这个(如果标签不存在,则创建标签)

{ "_id" : 1, "tags" : [ { "tag" : "foo" } ] }

然后我用这个查询来跟进......

db.userlinks.update (
    {_id: 1, tags: {tag: 'foo', links: {$nin: [{link: 'http://www.google.com'}]}}}, 
    {$push: {tags: {tag: 'foo', links: {link: 'http://www.google.com', date: '123'}}}}, 
    {upsert: true}
)

但我收到此错误:“无法将$ push / $ pushAll修饰符应用于非数组”

我很确定问题出在第二个查询的'update'组件中,​​但我不确定如何修复它。任何帮助将不胜感激。

修改

我的第一个查询现在是......(感谢Joe)

db.userlinks.update (
    {_id: 1, tags: {$nin: [{tag:'foo'}]}}, 
    {$push: {'tags': {tag:'foo', links:[]}}}, 
    {upsert: true}
)

我的第二个查询现在是......

db.userlinks.update (
    {_id: 1, 'tags.tag': 'foo'}, 
    {$push: {'tags.$.links': {link: 'http://www.google.com', date: '123'} } }
)

成功地将链接推送到'links'数组,但它也允许重复。我不能允许重复链接。 $ addToSet类型有效,但是如果日期发生变化,那么它仍会插入重复的链接。

有没有办法检查第二个查询的“查询”部分是否存在链接,或者只检查某些字段匹配时是否添加addToSet?

2 个答案:

答案 0 :(得分:18)

我终于明白了......虽然如果有人能看到更好的方法,请将其作为答案添加。

// create the userlinks collection if it doesn't exist
// also add a tag 'foo' into it, but only if the tag doesn't exist
db.userlinks.update (
    {_id: '1', 'tags.tag': {$nin: ['foo']}}, 
    {$push: {'tags': {tag:'foo', links:[]}}},
    {upsert: true}
)

// add a link into the 'foo' tag, but only if the link doesn't exist
db.userlinks.update(
    {_id: '1', 'tags.tag': 'foo', 'tags.links.link': {$nin: ['http://foobar.com']}},
    {$push: {'tags.$.links': {link: 'http://foobar.com', date: '15'} } }
)

答案 1 :(得分:1)

也许将您的第一个查询更改为:

db.userlinks.update (
    {_id: 1, tags: {$nin: [{tag:'foo'}]}}, 
    {$push: {'tags': {tag:'foo', links:[]}}}, 
    {upsert: true}
)

$ push操作应该只影响链接,而不影响标记。

{$push: {'tags.links': {link: 'http://www.google.com', date: '123'} } },