2012-01-05 46 views
2

所以我使用mongoose和node.js来访问一个mongodb数据库。我想根据一个数字碰撞每个结果(如果没有碰撞,它们按照创建的日期排序)。例如:如何在mongodb/mongoose查询中基于关闭参数更改结果位置?

{ name: 'A', 
    bump: 0 }, 

{ name: 'B', 
    bump: 0 }, 

{ name: 'C', 
    bump: 2 }, 

{ name: 'D', 
    bump: 1 } 

会在订单中retreived:C,A,d,B.这怎么可能实现(不通过数据库中的每个条目迭代)?

+0

所以你想要它根据1,2,1,0排序? – glortho 2012-01-05 02:58:47

+0

不,我想结果“碰到”了很多结果 – sdfadfaasd 2012-01-06 00:04:01

+0

请举一个例子......“我有x存储在数据库中。一个请求进来,我想它做...” – 2012-01-06 15:16:12

回答

1

让我们猜你的代码是变量response(这是一个数组),那么我会做:

response.sort(function(obj1, obj2){ 
    return obj2.bump - obj1.bump; 
}); 

,或者如果你也想采取名记顺序:

response.sort(function(obj1, obj2){ 
    var diff = obj2.bump - obj1.bump; 
    var nameDiff = (obj2.name > obj1.name)?-1:((obj2.name < obj1.name)?1:0); 
    return (diff == 0) ? nameDiff : diff; 
}); 
+0

您的第一个将返回C D A B,而不是C A D B。他希望按照颠簸移动的文档 - A和B都有0个颠簸,所以它们保持在原来的位置。C有2个颠簸,所以它比A高2个,因此这个列表将是C A B D。但是然后D有1个凹凸,所以它上升1,高于B,所以最后的列表是C A D B. – glortho 2012-01-08 20:43:09

+0

@Jed我猜他写错了。我的答案是解释凹凸为“秩序”... – 2012-01-09 04:38:23

+0

这不会迭代列表?我承认不是一个MongoDB专家,但我不确定如何在不迭代任何语言的情况下对列表进行排序。 – gilly3 2012-01-13 22:19:48

1

我不认为纯粹的基于查询的解决方案可能与您的文档模式(我假设你有createdDatebump字段)。相反,我建议叫sortorder,让您所需检索订单跟踪单场:

  1. sortorder最初创建时间戳。如果没有“颠簸”,按此字段进行排序会提供正确的顺序。
  2. 如果出现“凹凸”,sortorder将失效。因此,只需更正sortorder的值:每次发生“颠簸”时,都会将颠簸文档的sortorder字段与直接位于其前面的文档进行交换。这实际上按照排序顺序“颠簸”文档。
  3. 查询时,按sortorder排序。

如果在别处没有使用,您可以删除字段bumpcreatedDate


另外,大多数社交网站并不直接根据投票数(或“颠簸”)来操纵帖子的展示位置。相反,票数用于计算得分。然后帖子按这个分数排序和显示。在你的情况下,你应该将createdDatebumps组合成一个单一的分数,可以在查询中排序。

本网站(StackOverflow.com)有关于如何确定“热门”问题的相关meta discussion。我认为甚至有一场比赛想出一个新的公式。元问题还分享了其他两个流行的社交新闻网站使用的公式:Y Combinator Hacker News和Reddit。

1

不是一个愉快的答案,但您要求的解决方案是不现实的。以下是我的建议:

  1. OrderPosition属性添加到您的对象而不是凹凸。

  2. 认为“碰撞”是一个事件。它最好表现为一个事件处理函数。当某件商品被商业逻辑中的任何触发器“碰撞”时,需要调整商品的集合。

    var currentOrder = this.OrderPosition 
    this.OrderPosition = currentOrder - bump; // moves your object up the list 
    // write a foreach loop here, iterating every item AFTER the items unadjusted 
    // order, +1 to move them all down the list one notch.  
    

这确实需要通过许多项目迭代,我知道你正试图阻止,但我不认为有任何其他的方式来安全地确保您的项目排序的完整性 - 特别是当相对于后来发生的其他拉集合。

+0

我认为你的方法是正确的,但你的实现是关闭的。你所要做的就是在项目前面交换地点。你不需要迭代列表,除非找到前一个项目。 – gilly3 2012-01-13 22:23:41

+0

@ gilly3如果它仅仅是一个列表对象,并且你正在交换位置,那么你是正确的。但据我了解,持久性收集中的每个项目都有一个订单,如果有任何项目被移动,其他项目必须进行调整。通过字段保持对象本身的值意味着每条记录都需要更新。相当没有效率,但不知道太多这个问题我不能提供更好的解决方案。 :) – 2012-01-13 22:58:38

2

尝试这样的事情。存储一个跟踪总线数的计数器,我们称之为thread_count,最初设置为0,所以有一个文件看起来像{thread_count:0}

每次创建一个新的线程,使用{$inc : {thread_count:1}}作为改性剂第一次调用findAndModify() - 即由1递增计数器并返回其新值。

然后,当您插入新线程时,将计数器的新值用作文档中字段的值,我们将其称为post_order

因此,您插入的每个文档每次的值都大于1。例如,插入第一个3个文件应该是这样的:

{name:'foo', post_order:1, created_at:... } // value of thread_count is at 1 {name:'bar', post_order:2, created_at:... } // value of thread_count is at 2 {name:'baz', post_order:3, created_at:... } // value of thread_count is at 3

那么有效,你可以通过post_order存在上升查询和秩序,它会在他们返回最旧到最新的顺序(或从最新到最旧的降序)。

然后,如果线条在其投票顺序中按其排列顺序“碰撞”,则可以在{$inc:{post_order:1}}的文档上调用update()。这将按照结果排序顺序将其前进1。如果两个线程对于post_order具有相同的值,created_at将区分哪一个先到达。所以你会按post_order, created_at排序。

您需要索引post_ordercreated_at