如何仅查找集合中具有一组ID的最新文档

How to find only newest document in collection with set of IDs

本文关键字:ID 最新 文档 具有一 何仅 查找 集合      更新时间:2023-09-26

我有一个集合Feeds和一个集合FeedElementsFeedElements文档通过feedId字段引用Feeds集合。此外,所有FeedElements文档都具有日期字段submitted

我只想发布最新的(由字段submitted确定)FeedElements文档,它恰好对应于一个Feeds文档。

以下是我尝试过的:

Meteor.publish('recentFeedElements', function (userId) {
    var feedIds = Feeds.find({'userId': userId}).map(function(feed) {
        return feed._id;
    });
    if (feedsIds.length > 0) return FeedElements.find({feedId: {$in: feedIds}}, {sort: {submitted: -1});
    else this.ready();
});

问题是,如果我在FeedElements.find()查询中结合使用limitsort,我只会得到所有Feed文档中的最新文档。然而,我希望有一个严格的1-1关系。因此,一个Feed文档->具有适当参考的最新FeedElements文档。

如果我理解得对,您希望每个提要都有lastActivity字段,该字段包含该提要最后提交的提要元素的时间戳。您希望此字段是被动的,并且不希望发布所有提要元素。

在这种情况下,聚合不是一个解决方案,因为Meteor不允许反应聚合。

您需要使用低级发布API:http://docs.meteor.com/#/full/meteor_publish(参见示例部分)。

低级发布API(this.added/this.removed/this.changed/others)使您能够完全控制通过Meteor.publish方法向客户端发送的数据。

以下是如何解决您的问题(我使用ES2015语法):


// client/client.js
Meteor.subscribe('userFeeds', { userId: 1 });

// lib/lib.js
Feeds = new Mongo.Collection('feeds');
FeedElements = new Mongo.Collection('FeedElements');

// server/server.js
// When setting `submitted` field, automatically set `submittedAt` field
// (I use matb33:collection-hooks here)
FeedElements.before.update((userId, elem, fieldNames, modifier) => {
  if (modifier.$set.submitted) {
    modifier.$set.submittedAt = new Date();
  }
});
function getLastActivity(feedId) {
  const lastSubmittedElem = FeedElements.findOne(
    {
      feedId,
      submitted: true,
    },
    {
      sort: { submittedAt: -1 }
    }
  );
  return lastSubmittedElem ? lastSubmittedElem.submittedAt : null;
}
Meteor.publish('userFeeds', function({ userId }) {
  const elemsObservers = {};
  // Observe all user feeds
  var feedObserver = Feeds.find({ userId: userId }).observeChanges({
    added: (feedId, fields) => {
      // Observe feed elements of the feed
      elemsObservers[feedId] = FeedElements.find({ feedId }).observeChanges({
        changed: (elemId, fields) => {
          // Update `lastActivity` field when new element is submitted
          if (fields.submitted) {
            this.changed('feeds', feedId, { lastActivity: fields.submittedAt });
          }
        },
      });
      fields.lastActivity = getLastActivity(feedId);
      this.added('feeds', feedId, fields);
    },
    changed: (feedId, fields) => {
      this.changed('feeds', feedId, fields);
    },
    removed: (feedId) => {
      elemsObservers[feedId].stop();
      delete elemsObservers[feedId];
      this.removed('feeds', feedId);
    },
  });
  this.ready();
  this.onStop(function() {
    feedObserver.stop();
    for (const feedId in elemsObservers) {
      elemsObservers[feedId].stop();
    }
  });
});

我还准备了github回购https://github.com/imkost/feeds.只有git clonemeteor run

您可以通过$sort、$group&第一

db.FeedElements.aggregate(
[
  { $match: { feedId: {$in:[1,2,3]}} },
  { $sort: { submitted: -1} },
  {
    $group:
    {
      _id: "$feedId",
      firstFeedElement: {$first : "$$ROOT"} // Get first whole document or you can take fields you want
    }
     }
   ]
)