【问题标题】:Implement feed with retweets in MongoDB在 MongoDB 中使用转推实现提要
【发布时间】:2020-05-18 10:04:08
【问题描述】:

我想在我的应用中实现转推功能。我使用Mongoose 并拥有UserMessage 模型,并将转推存储为{userId, createdAt} 类型的对象数组,其中createdAt 是发生转推的时间。消息模型有它自己的createdAt 字段。

我需要创建基于createdAt 字段合并在一起的原始消息和转发消息的提要。我坚持合并,无论是在单个查询中还是在 JavaScript 中单独进行合并。我可以通过一个查询在 Mongoose 中完成所有操作吗?如果不是如何找到最后一条消息的合并插入点和索引?

到目前为止,我只获取原始消息。

我的Message 模特:

const messageSchema = new mongoose.Schema(
  {
    fileId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'File',
      required: true,
    },
    userId: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'User',
      required: true,
    },
    likesIds: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User' }],
    reposts: [
      {
        reposterId: {
          type: mongoose.Schema.Types.ObjectId,
          ref: 'User',
        },
        createdAt: { type: Date, default: Date.now },
      },
    ],
  },
  {
    timestamps: true,
  },
);

编辑:现在我有了这个,但分页坏了。我正在尝试使用 newCreatedAt 字段作为光标,这似乎不起作用。当从前端传递 newCreatedAt 时,它在第二次调用中返回空数组。

  messages: async (
      parent,
      { cursor, limit = 100, username },
      { models },
    ) => {
      const user = username
        ? await models.User.findOne({
            username,
          })
        : null;

      const options = {
        ...(cursor && {
          newCreatedAt: {
            $lt: new Date(fromCursorHash(cursor)), 
          },
        }),
        ...(username && {
          userId: mongoose.Types.ObjectId(user.id),
        }),
      };

      console.log(options);

      const aMessages = await models.Message.aggregate([
        {
          $addFields: {
            newReposts: {
              $concatArrays: [
                [{ createdAt: '$createdAt', original: true }],
                '$reposts',
              ],
            },
          },
        },
        {
          $unwind: '$newReposts',
        },
        {
          $addFields: {
            newCreatedAt: '$newReposts.createdAt',
            original: '$newReposts.original',
          },
        },
        { $match: options },
        {
          $sort: {
            newCreatedAt: -1,
          },
        },
        {
          $limit: limit + 1,
        },
      ]);

      const messages = aMessages.map(m => {
        m.id = m._id.toString();
        return m;
      });
      //console.log(messages);

      const hasNextPage = messages.length > limit;
      const edges = hasNextPage ? messages.slice(0, -1) : messages; 

      return {
        edges,
        pageInfo: {
          hasNextPage,
          endCursor: toCursorHash(
            edges[edges.length - 1].newCreatedAt.toString(),
          ),
        },
      };
    },

这里是查询。工作的:

Mongoose: messages.aggregate([{
    '$match': {
        createdAt: {
            '$lt': 2020 - 02 - 02 T19: 48: 54.000 Z
        }
    }
}, {
    '$sort': {
        createdAt: -1
    }
}, {
    '$limit': 3
}], {})

还有一个不工作的:

Mongoose: messages.aggregate([{
    '$match': {
        newCreatedAt: {
            '$lt': 2020 - 02 - 02 T19: 51: 39.000 Z
        }
    }
}, {
    '$addFields': {
        newReposts: {
            '$concatArrays': [
                [{
                    createdAt: '$createdAt',
                    original: true
                }], '$reposts'
            ]
        }
    }
}, {
    '$unwind': '$newReposts'
}, {
    '$addFields': {
        newCreatedAt: '$newReposts.createdAt',
        original: '$newReposts.original'
    }
}, {
    '$sort': {
        newCreatedAt: -1
    }
}, {
    '$limit': 3
}], {})

【问题讨论】:

    标签: javascript mongodb mongoose merge


    【解决方案1】:

    这可以在一个查询中完成,尽管它有点 hack-ish:

    db.collection.aggregate([
        {
            $addFields: {
                reposts: {
                    $concatArrays: [[{createdAt: "$createdAt", original: true}],"$reports"]
                }
            }
        },
        {
            $unwind: "$reposts"
        },
        {
            $addFields: {
                createdAt: "$reposts.createdAt",
                original: "$reposts.original"
            }
        },
        {
            $sort: {
                createdAt: -1
            }
        }
    ]);
    

    您可以使用original 字段向查询添加任何其他逻辑,带有original: true 的文档是原始帖子,而其他文档是转推。

    【讨论】:

    • 只是我的reposts字段不再是对象数组[{createdAt, reposterId}]而是单个对象{createdAt, original: true}prnt.sc/qweoth
    • 我添加了代码和查询,你看看有什么问题吗?
    • '$lt': 2020 - 02 - 02 T19: 51: 39.000 Z 有什么匹配的吗?它应该是'$lt': ISODate(2020-02-02T19:51:39.000Z)
    • 这只是我使用的代码美化器,第一个查询具有相同的日期格式并且它正在工作。第二个查询返回空数组。
    • 除了匹配查询没有其他过滤掉文档
    猜你喜欢
    • 1970-01-01
    • 2021-02-08
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-05
    相关资源
    最近更新 更多