使用MongoDB数组作为堆栈

时间:2012-04-10 18:44:47

标签: mongodb stack

是否有人使用MongoDB的Array类型来实现堆栈?

我知道我可以append像这样的数组:

db.blogposts.update( {_id:5}, {$push: {comments: {by: "Abe", text:"First"}}})

这里,数组的末尾是堆栈的顶部...我没有看到在第零个索引处使用堆栈顶部实现此方法的方法,但我很想错

而且我知道我可以peek在数组的最后一个值,如下所示:

db.blogposts.find( {_id:5}, {comments: {$slice:-1}})

使用这样的实现,我可以在MongoDB更新语句中“查看”堆栈的顶部吗?这将给我语义,“如果堆栈的顶部是X,则将此项目推入堆栈”。我需要这是一个原子操作!

任何建议表示赞赏。谢谢!

2 个答案:

答案 0 :(得分:4)

不幸的是,目前无法完全按照您的描述进行此操作。

正如Chris Shain指出的那样,https://jira.mongodb.org/browse/SERVER-2191 - “$ push()到数组的前面”和类似https://jira.mongodb.org/browse/SERVER-1824 - “支持插入特定的数组索引”会有所帮助,但这些功能目前是没有针对特定的发布版本。

作为一种可能的解决方法,您可以在文档中添加名为“lastElement”(或等效项)的字段,其中包含推送到数组的最后一个元素的副本。在update语句中,您可以查询“lastElement”值,如果匹配,则同时将其设置为新值,并在单个原子操作中将相同的值推送到数组。

例如:

> db.blogposts.save({_id:5, comments:[{by: "Abe", text:"First"}], lastElement:{by: "Abe", text:"First"}})
> db.blogposts.find().pretty()
{
    "_id" : 5,
    "comments" : [
        {
            "by" : "Abe",
            "text" : "First"
        }
    ],
    "lastElement" : {
        "by" : "Abe",
        "text" : "First"
    }
}
> db.blogposts.update({"lastElement.text":"First"}, {$set:{lastElement:{by: "Joe", text:"Second"}}, $push:{comments:{by: "Joe", text:"Second"}}})
> db.blogposts.find().pretty()
{
    "_id" : 5,
    "comments" : [
        {
            "by" : "Abe",
            "text" : "First"
        },
        {
            "by" : "Joe",
            "text" : "Second"
        }
    ],
    "lastElement" : {
        "by" : "Joe",
        "text" : "Second"
    }
}
> 

作为替代方案,您可以考虑“原子操作”文档“当前更新”部分中概述的策略:http://www.mongodb.org/display/DOCS/Atomic+Operations

我意识到这些是解决方法,而不是理想的解决方案。希望以上内容可以帮助您实现目标,或者至少为您提供一些思考,以便您提出不同的解决方案。如果您这样做,请在此处分享,以便社区中可能遇到类似问题的任何成员都可以获得您的体验。谢谢。

答案 1 :(得分:3)

与mongoDB v2.6类似,现在通过$position运营商支持:http://docs.mongodb.org/manual/reference/operator/update/position/

db.blogposts.update(
  {_id:5}
  , {$push:
      {comments:
          {$each: {by: "Abe", text:"First"}
          , $position:0 }
      }
  }
);