Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript mongodb中用户排行榜得分的最佳设计_Javascript_Mongodb_Mongoose - Fatal编程技术网

Javascript mongodb中用户排行榜得分的最佳设计

Javascript mongodb中用户排行榜得分的最佳设计,javascript,mongodb,mongoose,Javascript,Mongodb,Mongoose,我在为我的游戏设计数据库时遇到了问题,游戏用户有3个不同权重的分数参数,分数是应用程序中特定动作的结果(did p、did Q或did L)。所以用户看起来像这样: { "_id": { "$oid" : "531f14324fe3ba6360335230" }, "p": 88, "q": 0, "l": 10, "totalScore":8.9 } { id: ObjectId, type:'q', time: DATE, userId:

我在为我的游戏设计数据库时遇到了问题,游戏用户有3个不同权重的分数参数,分数是应用程序中特定动作的结果(did p、did Q或did L)。所以用户看起来像这样:

{
  "_id": { "$oid" : "531f14324fe3ba6360335230" },
  "p": 88,
  "q": 0,
  "l": 10,
  "totalScore":8.9
}
{
    id: ObjectId,
    type:'q',
    time: DATE,
    userId: USER_ObjectId,
    entityId: ENTITY_ObjectId
}
{ 
    "userId": 123, 
    "username": "user1", 
    "type": "q", 
    "time": ISODate("2014-04-07T03:56:33.488Z")
},
{ 
    "userId": 123, 
    "username": "user1", 
    "type": "p", 
    "time": ISODate("2014-04-07T03:56:33.488Z")
},
{ 
    "userId": 456, 
    "username": "user2", 
    "type": "p", 
    "time": ISODate("2014-04-07T03:56:33.488Z")
}
db.events.aggregate([
    // Match the date range required
    { "$match": {
        "time": { 
            "$gte": new Date("2014-04-07"), 
            "$lt": new Date("2014-04-14") 
        }
    }},

    // Group and Reshape the matching documents
    { "$group": {
        "_id": "$userId",
        "username": { "$first": "$username" },
        "q" : { "$sum": { "$eq": [ "$type", "q" ] } },
        "p" : { "$sum": { "$eq": [ "$type", "p" ] } },
        "l" : { "$sum": { "$eq": [ "$type", "l" ] } }
    }},

    // Project to get a "score" value
    { "$project": {
        "username": 1,
        "p": 1,
        "q": 1,
        "l": 1,
        "score": { "$add": [
            "$q",
            { "$cond": [
                "$p",
                { "$divide": [ "$p", 10 ] },
                0
            ]},
            { "$cond": [
                "$l",
                { "$divide": [ "$l", 10 ] },
                0
            ]},
        ]} 
    }},

    // Sort the results by the "score" descending
    { "$sort": { "score": -1 } },

    // Optionally limit the results
    { "$limit": 10 }

])
其中p,q,l是具有不同权重的不同分数

我想根据用户的周/月活动查询信息,这意味着在p、q、l得分最高的用户将是本周的顶级用户

我完全无法理解如何建立适当的体系结构,既支持按周/月查询日期,又支持以有效方式加权计算分数,假设我也想与周围的用户建立排行榜,并拥有当前用户的位置

-----------------q--------p--------l------
4. user121      25       5         0
5. currentUser  5        7        28
6. user77       3        2        43
-----
非常感谢你的帮助

UPD: 这是设计的初稿

我有actions集合,其中包含每个用户生成的操作的文档,如下所示:

{
  "_id": { "$oid" : "531f14324fe3ba6360335230" },
  "p": 88,
  "q": 0,
  "l": 10,
  "totalScore":8.9
}
{
    id: ObjectId,
    type:'q',
    time: DATE,
    userId: USER_ObjectId,
    entityId: ENTITY_ObjectId
}
{ 
    "userId": 123, 
    "username": "user1", 
    "type": "q", 
    "time": ISODate("2014-04-07T03:56:33.488Z")
},
{ 
    "userId": 123, 
    "username": "user1", 
    "type": "p", 
    "time": ISODate("2014-04-07T03:56:33.488Z")
},
{ 
    "userId": 456, 
    "username": "user2", 
    "type": "p", 
    "time": ISODate("2014-04-07T03:56:33.488Z")
}
db.events.aggregate([
    // Match the date range required
    { "$match": {
        "time": { 
            "$gte": new Date("2014-04-07"), 
            "$lt": new Date("2014-04-14") 
        }
    }},

    // Group and Reshape the matching documents
    { "$group": {
        "_id": "$userId",
        "username": { "$first": "$username" },
        "q" : { "$sum": { "$eq": [ "$type", "q" ] } },
        "p" : { "$sum": { "$eq": [ "$type", "p" ] } },
        "l" : { "$sum": { "$eq": [ "$type", "l" ] } }
    }},

    // Project to get a "score" value
    { "$project": {
        "username": 1,
        "p": 1,
        "q": 1,
        "l": 1,
        "score": { "$add": [
            "$q",
            { "$cond": [
                "$p",
                { "$divide": [ "$p", 10 ] },
                0
            ]},
            { "$cond": [
                "$l",
                { "$divide": [ "$l", 10 ] },
                0
            ]},
        ]} 
    }},

    // Sort the results by the "score" descending
    { "$sort": { "score": -1 } },

    // Optionally limit the results
    { "$limit": 10 }

])
其他类型也一样

所以,当游戏中发生动作时,我会创建这样的文档,并在scores文档中为用户增加适当的类型字段。 在此之后,我根据我的公式计算totalScore字段:

totalscore = q + p/10 + l/100

现在我可以根据总分进行查询和排序,但它没有关于该分数是否为过去七天的数据,仍然不知道如何实现这一点。

根据上次更新,这似乎是正确的,但我可能会为设计提供一些“tweeks”,并解决问题的日期范围部分

虽然您可以使用mongoose使用
populate
做一些好事,但仍然值得记住的是,这种“连接”只是模拟的,因为实际发生的是对数据库进行额外的查询以检索“相关”项

因此,在使用MongoDB时,最好将要使用的信息保存在同一个集合中。因此,对于这里的简单示例,我将在这些“事件”类型的条目中保留“用户名”。我这样做是因为这是总结这一点时将使用的信息。因此,“事件”(我称之为事件)的文档如下所示:

{
  "_id": { "$oid" : "531f14324fe3ba6360335230" },
  "p": 88,
  "q": 0,
  "l": 10,
  "totalScore":8.9
}
{
    id: ObjectId,
    type:'q',
    time: DATE,
    userId: USER_ObjectId,
    entityId: ENTITY_ObjectId
}
{ 
    "userId": 123, 
    "username": "user1", 
    "type": "q", 
    "time": ISODate("2014-04-07T03:56:33.488Z")
},
{ 
    "userId": 123, 
    "username": "user1", 
    "type": "p", 
    "time": ISODate("2014-04-07T03:56:33.488Z")
},
{ 
    "userId": 456, 
    "username": "user2", 
    "type": "p", 
    "time": ISODate("2014-04-07T03:56:33.488Z")
}
db.events.aggregate([
    // Match the date range required
    { "$match": {
        "time": { 
            "$gte": new Date("2014-04-07"), 
            "$lt": new Date("2014-04-14") 
        }
    }},

    // Group and Reshape the matching documents
    { "$group": {
        "_id": "$userId",
        "username": { "$first": "$username" },
        "q" : { "$sum": { "$eq": [ "$type", "q" ] } },
        "p" : { "$sum": { "$eq": [ "$type", "p" ] } },
        "l" : { "$sum": { "$eq": [ "$type", "l" ] } }
    }},

    // Project to get a "score" value
    { "$project": {
        "username": 1,
        "p": 1,
        "q": 1,
        "l": 1,
        "score": { "$add": [
            "$q",
            { "$cond": [
                "$p",
                { "$divide": [ "$p", 10 ] },
                0
            ]},
            { "$cond": [
                "$l",
                { "$divide": [ "$l", 10 ] },
                0
            ]},
        ]} 
    }},

    // Sort the results by the "score" descending
    { "$sort": { "score": -1 } },

    // Optionally limit the results
    { "$limit": 10 }

])
当然还有其他领域,但这些是我们将重点关注的领域

要在某个日期范围内将这些内容组合在一起,您可以执行以下操作:

{
  "_id": { "$oid" : "531f14324fe3ba6360335230" },
  "p": 88,
  "q": 0,
  "l": 10,
  "totalScore":8.9
}
{
    id: ObjectId,
    type:'q',
    time: DATE,
    userId: USER_ObjectId,
    entityId: ENTITY_ObjectId
}
{ 
    "userId": 123, 
    "username": "user1", 
    "type": "q", 
    "time": ISODate("2014-04-07T03:56:33.488Z")
},
{ 
    "userId": 123, 
    "username": "user1", 
    "type": "p", 
    "time": ISODate("2014-04-07T03:56:33.488Z")
},
{ 
    "userId": 456, 
    "username": "user2", 
    "type": "p", 
    "time": ISODate("2014-04-07T03:56:33.488Z")
}
db.events.aggregate([
    // Match the date range required
    { "$match": {
        "time": { 
            "$gte": new Date("2014-04-07"), 
            "$lt": new Date("2014-04-14") 
        }
    }},

    // Group and Reshape the matching documents
    { "$group": {
        "_id": "$userId",
        "username": { "$first": "$username" },
        "q" : { "$sum": { "$eq": [ "$type", "q" ] } },
        "p" : { "$sum": { "$eq": [ "$type", "p" ] } },
        "l" : { "$sum": { "$eq": [ "$type", "l" ] } }
    }},

    // Project to get a "score" value
    { "$project": {
        "username": 1,
        "p": 1,
        "q": 1,
        "l": 1,
        "score": { "$add": [
            "$q",
            { "$cond": [
                "$p",
                { "$divide": [ "$p", 10 ] },
                0
            ]},
            { "$cond": [
                "$l",
                { "$divide": [ "$l", 10 ] },
                0
            ]},
        ]} 
    }},

    // Sort the results by the "score" descending
    { "$sort": { "score": -1 } },

    // Optionally limit the results
    { "$limit": 10 }

])
因此,所有这些都会对时间段内基于“事件”的条目中的每个用户的结果进行分组,计算总分(注意不要除以0),然后对结果进行排序,以使最高分数位于顶部

您甚至可以执行类似的查询,从每周或其他时间间隔中查找排名最高的用户:

db.events.aggregate([
    // Match the date range required - one year as a sample
    { "$match": {
        "time": { 
            "$gte": new Date("2014-01-01"), 
            "$lt": new Date("2015-01-01") 
        }
    }},


    // Group and Reshape the matching documents
    { "$group": {
        "_id": { 
            "week": { "$week": "$time" },
            "userId": "$userId"
        },
        "username": { "$first": "$username" },
        "q" : { "$sum": { "$eq": [ "$type", "q" ] } },
        "p" : { "$sum": { "$eq": [ "$type", "p" ] } },
        "l" : { "$sum": { "$eq": [ "$type", "l" ] } }
    }},

    // Project to get a "score" value
    { "$project": {
        "username": 1,
        "p": 1,
        "q": 1,
        "l": 1,
        "score": { "$add": [
            "$q",
            { "$cond": [
                "$p",
                { "$divide": [ "$p", 10 ] },
                0
            ]},
            { "$cond": [
                "$l",
                { "$divide": [ "$l", 10 ] },
                0
            ]},
        ]} 
    }},

    // Sort by highest score for each week
    { "$sort": { "_id.week": 1, "score": -1 } },

    // Group again to get the highest value in each week
    { "$group": {
        "_id": "$_id.week",
        "userId": { "$first": "$_id.userId" },
        "username": { "$first": "$username" },
        "q": { "$first": "$q" },
        "p": { "$first": "$p" },
        "l": { "$first": "$l" },
        "score": { "$first": "$score" }, 
    }}

])
如果您需要运行总计,那么您最好将这些结果“预聚合”到另一个集合中,并在总体性能方面保持谨慎的周数,甚至可以按周或任何最适合您的时间段保持运行总计


因此,这里有一点可供参考,但主要文档可以查看各种,尤其是,因为这些文档将允许您根据日期的不同组成部分(周、月、日、小时或年)进行“分组”。

答案中是否有不符合您需要的内容?您还没有回复。谢谢!但是我不明白这个设计怎么能让我周围的用户得分?