Mongoose: find()忽略重复的值

问题描述 投票:0回答:1

我有一个 "聊天 "的猫鼬 Schema 它具有以下属性。

const schema = mongoose.Schema({
    ...
    recipient: {
        type: mongoose.Types.ObjectId,
        required: true,
        ref: 'User',
    },
    sender: {
        type: mongoose.Types.ObjectId,
        required: true,
        ref: 'User',
    },
    content: {
        type: String,
    },
    ...
}, {
    timestamps: true,
});

一般来说,我想获取一个用户拥有的每条覆盖信息的最后一条信息。意味着我需要提供一个用户id(可以存储在 senderrecipient 字段),并取回最后一条消息(用 createdAt)的用户与其他每个用户的关系。

例子:假设我有以下内容 documents:

[
  {
    recipient: "One",
    sender: "Two",
    createdAt: ISODate("2014-01-01T08:00:00Z"),

  },
  {
    recipient: "One",
    sender: "Three",
    createdAt: ISODate("2014-02-15T08:00:00Z")
  },
  {
    recipient: "Two",
    sender: "One",
    createdAt: ISODate("2014-02-16T12:05:10Z")
  }
]

把 "一 "作为输入 -- 从 "一 "中得到的理想结果 Model.find(...) 是的,我有一个mongoose.Schema,它有以下属性: const schema = mongoose.Schema({ ..:

[
  {
    recipient: "One",
    sender: "Three",
    createdAt: ISODate("2014-02-15T08:00:00Z")
  },
  {
    recipient: "Two",
    sender: "One",
    createdAt: ISODate("2014-02-16T12:05:10Z")
  }
]
node.js mongodb mongoose nosql
1个回答
1
投票

使用示例数据。

[
  {
    recipient: "One",
    sender: "Two",
    createdAt: ISODate("2014-01-01T08:00:00Z"),
    content: "Hi Mr. One! - Two"
  },
  {
    recipient: "One",
    sender: "Three",
    createdAt: ISODate("2014-02-15T08:00:00Z"),
    content: "Hello One! - Three"
  },
  {
    recipient: "Two",
    sender: "One",
    createdAt: ISODate("2014-02-16T12:05:10Z"),
    content: "Whats up, Two? - One"
  }
]

看一下下面的聚合: https:/mongoplayground.netpDTSDWX3aLWe

它...

  • 用途 匹配 来过滤所有收件人或发件人的邮件。返回与当前用户匹配的信息 (One)
  • 增加了一个 conversationWith 领域使用 $addFields 其中包含 recipient 如果是信息 向用户一sender 如果是信息 由用户One发送
  • 按日期对邮件进行排序,使用 $sort
  • 将所有的信息用 $组 由新 conversationWith 字段,并将最近的信息返回为 firstMessage

完整的聚合流水线。

db.collection.aggregate([
  {
    $match: {
      $and: [
        {
          $or: [
            {
              recipient: "One"
            },
            {
              sender: "One"
            }
          ],

        },

      ]
    }
  },
  {
    $addFields: {
      conversationWith: {
        $cond: {
          if: {
            $eq: [
              "$sender",
              "One"
            ]
          },
          then: "$recipient",
          else: "$sender"
        }
      }
    }
  },
  {
    $sort: {
      createdAt: -1
    }
  },
  {
    $group: {
      _id: "$conversationWith",
      firstMessage: {
        $first: "$$ROOT"
      }
    }
  }
])

利用mongoplayground你可以逐一删除聚合步骤 看看每个步骤的作用。

试试。

  • 只有 匹配 步骤
  • 匹配 + $addFields
  • 匹配 + $addFields + $sort
  • [..]

以获得最佳理解。


2
投票

你可以通过下面的查询汇总来实现这个目的。

工作实例-- https:/mongoplayground.netpwEi4Y6IZJ2v。

db.collection.aggregate([
  {
    $sort: {
      recipient: 1,
      createdAt: 1
    }
  },
  {
    $group: {
      _id: "$recipient",
      createdAt: {
        $last: "$createdAt"
      }
    }
  },
  {
    $project: {
      _id: 0,
      recipient: "$_id",
      createdAt: "$createdAt"
    }
  }
])

如果你有两个字段要匹配,那么你可以使用下面的查询方式。

工作实例 - https:/mongoplayground.netpRk5MxuphLOT。

db.collection.aggregate([
  {
    $match: {
      $or: [
        {
          sender: "One"
        },
        {
          recipient: "One"
        }
      ]
    }
  },
  {
    $addFields: {
      other: {
        $cond: {
          if: {
            $eq: [
              "$recipient",
              "One"
            ]
          },
          then: "$sender",
          else: "$recipient"
        }
      }
    }
  },
  {
    $sort: {
      createdAt: 1
    }
  },
  {
    $group: {
      _id: "$other",
      createdAt: {
        $last: "$createdAt"
      },
      recipient: {
        $last: "$recipient"
      },
      sender: {
        $last: "$sender"
      }
    }
  },
  {
    $project: {
      _id: 0,
      recipient: "$recipient",
      sender: "$sender",
      createdAt: "$createdAt"
    }
  }
])

0
投票

如果你想依靠mongodb来过滤掉重复的内容,最好通过创建一个 "不允许有重复的内容"。唯一指数.

由于你的收件人似乎是嵌套在一个父方案中,我将在nodejs中过滤重复的内容,因为在mongodb查询中很难解开这个问题。鲜明 功能或 集料管道 并从中受到启发 本文

© www.soinside.com 2019 - 2024. All rights reserved.