1

我创建了一个用于跟踪用户会话的集合。我想根据登录时间获取每个用户的最后一个会话。假设我的收藏中有一些文件。

{
    "_id" : BinData(3,"LkNkGFrvldtTyHmLp5CirA=="),
    "createdTime" : ISODate("2017-09-22T06:37:17.620Z"),
    "userName" : "testUser1",
    "loggedOnDuration" : NumberLong(10),
    "loginTime" : ISODate("2017-09-22T06:37:17.620Z"),
    "logoutTime" : ISODate("2017-09-23T06:37:17.620Z"),
}
{
    "_id" : BinData(3,"B0R7SkeZ30rCjsp/Kftphw=="),
    "createdTime" : ISODate("2017-09-22T06:42:17.620Z"),
    "userName" : "testUser1",
    "loggedOnDuration" : NumberLong(10),
    "loginTime" : ISODate("2017-09-22T06:42:17.620Z"),
    "logoutTime" : ISODate("2017-09-23T06:37:17.620Z"),
}
{
    "_id" : BinData(3,"B0R7SkeZ30rCjsp/Kftphw=="),
    "createdTime" : ISODate("2017-09-22T06:45:17.620Z"),
    "userName" : "testUser2",
    "loggedOnDuration" : NumberLong(10),
    "loginTime" : ISODate("2017-09-22T06:45:17.620Z"),
    "logoutTime" : ISODate("2017-09-23T06:37:17.620Z"),
}
{
    "_id" : BinData(3,"B0R7SkeZ30rCjsp/Kftphw=="),
    "createdTime" : ISODate("2017-09-24T06:50:17.620Z"),
    "userName" : "testUser2",
    "loggedOnDuration" : NumberLong(10),
    "loginTime" : ISODate("2017-09-24T06:50:17.620Z"),
    "logoutTime" : ISODate("2017-09-24T06:59:17.620Z"),
}

我只想为每个用户获取一个具有最大创建时间的文档。输出应该是这样的 -

{
    "_id" : BinData(3,"B0R7SkeZ30rCjsp/Kftphw=="),
    "createdTime" : ISODate("2017-09-22T06:42:17.620Z"),
    "userName" : "testUser1",
    "loggedOnDuration" : NumberLong(10),
    "loginTime" : ISODate("2017-09-22T06:42:17.620Z"),
    "logoutTime" : ISODate("2017-09-23T06:37:17.620Z"),
}
{
    "_id" : BinData(3,"B0R7SkeZ30rCjsp/Kftphw=="),
    "createdTime" : ISODate("2017-09-24T06:50:17.620Z"),
    "userName" : "testUser2",
    "loggedOnDuration" : NumberLong(10),
    "loginTime" : ISODate("2017-09-24T06:50:17.620Z"),
    "logoutTime" : ISODate("2017-09-24T06:59:17.620Z"),
}

我正在使用 MongoCollection 类进行 MongoDB 操作。如何使用 MongoCollection 库获得此输出?

4

3 回答 3

0

我们可以使用$sort$first运算符来实现这一点。

db.mycollection.aggregate( [
    { $sort : { userName : -1, createdTime: -1 } },
    {
        $group: 
        {
            _id: {userName:"$userName" }, 
            maxCreatedItem: 
            { 
                $first:  
                { 
                    _id:"$_id", 
                    createdTime: "$createdTime", 
                    userName: "$userName", 
                    loggedOnDuration: "$loggedOnDuration", 
                    loginTime:"$loginTime", 
                    logoutTime:"$logoutTime" 
                } 
            }
        }
    },
    {
        $replaceRoot: { newRoot: "$maxCreatedItem" }
    }
 ])

结果:

{
    "_id" : ObjectId("59e99f9bb0e16378d5e80d48"),
    "createdTime" : ISODate("2017-09-22T06:42:17.620Z"),
    "userName" : "testUser1",
    "loggedOnDuration" : NumberLong(10),
    "loginTime" : ISODate("2017-09-22T06:42:17.620Z"),
    "logoutTime" : ISODate("2017-09-23T06:37:17.620Z")
}
{
    "_id" : ObjectId("59e99f9bb0e16378d5e80d4a"),
    "createdTime" : ISODate("2017-09-24T06:50:17.620Z"),
    "userName" : "testUser2",
    "loggedOnDuration" : NumberLong(10),
    "loginTime" : ISODate("2017-09-24T06:50:17.620Z"),
    "logoutTime" : ISODate("2017-09-24T06:59:17.620Z")
}
于 2017-10-20T08:08:13.860 回答
0

您可以使用聚合框架https://docs.mongodb.com/manual/aggregation/将会话文档按用户名分组并获取最大登录时间。使用 mongo shell,聚合管道将如下所示:

db.session.aggregate([
  {$group: {_id:"$userName", loginTime: {$max: "$loginTime"}}}
])

按用户名分组的单个阶段。

这可以在java中使用重新创建BasicDBObjects

final MongoCollection<Document> mongoCollection = database.getCollection("sessions");

List<Bson> pipeline = new ArrayList<>();
BasicDBObject groupStage = new BasicDBObject("$group",
  new BasicDBObject("_id", "$userName")
  .append("loginTime", new BasicDBObject("$max", "$loginTime")));
pipeline.add(groupStage);

AggregateIterable<Document> result = mongoCollection.aggregate(pipeline);
于 2017-10-03T13:00:40.643 回答
0

嗯,我认为这应该工作:

    MongoCollection<Document> collection = database.getCollection("your_collection");

    collection.find(Filters.eq("userName", "aUserName"))
            .sort(Sorts.descending("loginTime"))
            .first(); //get highest element

或者,如果您想要多个条目,只需使用.limit(<amount>)并遍历结果。

于 2017-10-03T13:02:57.650 回答