【问题标题】:How to return only the first occurrence of an ID with Mongoose?如何使用 Mongoose 只返回第一次出现的 ID?
【发布时间】:2016-10-01 15:04:56
【问题描述】:

我有一个名为Messages 的大型集合,如下所示:

{
   user: 94fg844f,
   event: null,
   group: null,
   name: "Jake",
   text: "Hello world"
}, {
   user: fje93jrg4,
   event: null,
   group: null,
   name: "Bob"
   text: "Testing"
}, {
   user: fje93jrg4,
   event: null,
   group: null,
   name: "Bob"
   text: "Text here"
}, {
   user: null,
   event: d0j3n9fn3,
   group: null,
   name: "My Event"
   text: "Testing 2"
}, {
   user: null,
   event: d0j3n9fn3,
   group: null,
   name: "My Event"
   text: "Another text"
}

我需要获取用户、事件和组的第一次出现。

例如,由于用户fje93jrg4 出现了两次,我只想获取带有Testing 文本的文档,因为带有Text here 文本的文档比它旧。 eventd0j3n9fn3 也是如此。它出现了两次,虽然我只是想用Testing 2 的文本找回第一个文档。

我查看了distinct,尽管它似乎只支持一个搜索词,例如user 而不是usereventgroup

上面的最终结果是:

{
   user: 94fg844f,
   event: null,
   group: null,
   name: "Jake",
   text: "Hello world"
}, {
   user: fje93jrg4,
   event: null,
   group: null,
   name: "Bob"
   text: "Testing"
}, , {
   user: null,
   event: d0j3n9fn3,
   group: null,
   name: "My Event"
   text: "Testing 2"
}

我的猜测是我可能不得不使用aggregate$first 或类似的东西。执行 3 个不同查询的问题是我需要应用一个限制,以便我总是得到 10 个结果。例如,组合中可能没有最近的groups,只有events 和users。

【问题讨论】:

  • 你能把这三个搜索加在一起吗?此外,这 3 个搜索似乎非常不同。用于输出的数组几乎看起来不合适,因为索引没有意义。
  • @4castle - 唯一的可能就是无法应用限制。
  • 如何识别每个用户的第一个和最后一个文档。您不能依赖文档在集合中的顺序。
  • @user3100115 - 应该说,我的错。我可以使用“_id”作为排序,也可以使用每个文档具有的自定义“创建”字段。

标签: node.js mongodb mongoose mongodb-query aggregation-framework


【解决方案1】:

我们可以使用聚合框架来做到这一点。首先我们需要通过user 和“_id”来$sort。从那里,我们然后通过“用户”$group 并使用$last 累加器运算符返回每个用户的最后一个文档。请注意,如果我们按降序对文档进行排序,我们也可以使用$first 累加器运算符,但是按升序排序并使用$last 可以明确我们的意图。

db.collection.aggregate([
    { "$sort": { "user": 1, "_id": -1 } }, 
    { "$group": { 
        "_id": "$user", 
        "user": { "$last": "$$ROOT" } 
    }} 
])

产生:

{
    "_id" : "fje93jrg4",
    "user" : {
        "_id" : 2,
        "user" : "fje93jrg4",
        "event" : null,
        "group" : null,
        "name" : "Bob",
        "text" : "Testing"
    }
}
{
    "_id" : "94fg844f",
    "user" : {
        "_id" : 1,
        "user" : "94fg844f",
        "event" : null,
        "group" : null,
        "name" : "Jake",
        "text" : "Hello world"
    }
}
{
    "_id" : null,
    "user" : {
        "_id" : 4,
        "user" : null,
        "event" : "d0j3n9fn3",
        "group" : null,
        "name" : "My Event",
        "text" : "Testing 2"
    }
}

我们可能想在管道中添加$project,但这样做会导致性能下降。但是,如果不需要返回文档中的所有键/值对,它将减少通过线路发送的数据量以及用于在客户端解码文档的时间和内存。

$project 舞台如下所示:

{ "$project": {
    "_id": "$user._id",
    "user": "$user.user",
    "event": "$user.event",
    "group": "$user.group",
    "name": "$user.name",
    "text": "$user.text"
}}

【讨论】:

  • 看起来不错!尽管在 userevent 具有相同 ID 的罕见情况下会发生什么?它们是不同的集合,我的 Messages 集合只是引用了它们的 ID。
  • 这里不需要考虑“事件”字段。您所需要的只是您在comment 中提到的“用户”和“_id”或“创建”字段
【解决方案2】:

完美运行:

db.getCollection('Mytest').aggregate([{ $match : { user: "fje93jrg4" }},{$limit:1}])

【讨论】:

  • 我认为你根本没有读过这个问题。我不是在搜索特定用户,我需要返回每个用户、组和事件的第一个结果...
猜你喜欢
  • 2012-02-02
  • 1970-01-01
  • 1970-01-01
  • 2019-05-01
  • 2019-05-08
  • 1970-01-01
  • 2012-11-26
  • 2019-12-20
  • 1970-01-01
相关资源
最近更新 更多