如何在更新时对数组进行排序

时间:2014-12-14 21:05:53

标签: mongodb mongoose mongoid pymongo mongodb-query

例如我在mongo的博客文章:

{
  title: 'Some title',
  text: 'Text',
  tags: ['one', 'two', 'three']
}

有没有优雅的方式来改变tags订购? (任何语言或框架)

改变排序的

upd:我的意思是能够以某种自定义的方式改变元素的顺序 - ex ['two','one','three']

我认为有一些显而易见的方法并不完美:

  1. 如果我copy and paste(从服务器到客户端并返回)每次编辑帖子时都会标记 - 有一天会出现竞争条件。

    示例:

    如果Ann开始处理帖子(并加载了3个标签),那么Bob会快速广告一个标签并保存帖子,Ann会破坏他的编辑,因为她有一个旧数据。

  2. 我可以检查服务器端列表的长度。但是用手做这件事似乎有些奇怪和错误 - 也许有人已经做过了吗?

  3. 我可以将嵌套列表放入特殊的集合中,并使用整数order - 相关的数据库样式。

  4. 那有什么不对?

    • 也许我错过了一些已经按照订单做正确的工具。

    • 也许我只是不知道实际嵌套列表的用途(也许订购不是他们的好方面)。

    我很感激这个问题的任何帮助。

1 个答案:

答案 0 :(得分:4)

MongoDB有自己的方法来“排序”数组的值,你可以在修改时没有实际添加或删除数组中存在的任何元素。这意味着它在服务器上以原子方式执行,无需通过线路读取文档,然后将其发回。

考虑您的示例文档,您可以这样:

db.sample.update(
    {},
    { "$push": { "tags": { "$each": [], "$sort": 1 } } },
    { "multi": true}
)

哪会产生:

{ 
    "title" : "Some title",
    "text" : "Text",
    "tags" : [ "one", "three", "two" ]
}

如果您想更具体地维护订单,您可以随时将附加字段作为子文档添加到数组内容中:

{ 
    "title" : "Some title",
    "text" : "Text",
    "tags" : [ 
        { "name": "one", "pos": 1 },
        { "name": "three", "pos": 3 },
        { "name": "two", "pos": 2 }
    ]
}

然后应用类似的 $sort 操作:

db.sample.update(
    {}, 
    { "$push": { "tags": { "$each": [], "$sort": { "pos": 1 } } }},
    { "$multi": true }
)

结果如下:

{
    "title" : "Some title", 
    "text" : "Text", 
    "tags" : [ 
        { "name" : "one", "pos" : 1 },
        { "name" : "two", "pos" : 2 },
        { "name" : "three", "pos" : 3 }
    ] 
}

一开始有点模糊,但与$each修饰符一起,$sort修饰符$push会在更新时对数组内容进行排序。因此,即使向数组添加“nothing”,如 $each 的空数组参数所表示的那样,然后将排序应用于整个内容。

当然,在每次更新中移动数组内容都需要付出代价,即使在添加实际值时,这也会起作用,当您“删除”项目时,它必须是一个单独的操作。 $pull 操作没有这样的现实参数。

您可能想要考虑仅使用存储文档中的第二个表单,但如果这成为应用程序性能的问题,请执行实际的“排序”客户端。