Node.js 向端点结果添加分页光标和其他功能

Node.js 向端点结果添加分页光标和其他功能,node.js,loopbackjs,strongloop,Node.js,Loopbackjs,Strongloop,Strongloop api非常适合开箱即用。然而,我目前正在尝试进行一些定制。我试图向类别模型中添加一个远程方法,该方法与端点数据一起返回以下内容:每页,总计,分页(详见下文)。对于分页而言,前和后是基于gameId的参数限制将默认为5。在前面提到的结果中附加的最佳方式是什么 例如,http://localhost:3000/api/Categories/1004/games/mature?before=1000053将返回所有gameId小于1000053和之前的所有gameId大于1000

Strongloop api非常适合开箱即用。然而,我目前正在尝试进行一些定制。我试图向
类别
模型中添加一个远程方法,该方法与端点数据一起返回以下内容:
每页
总计
分页
(详见下文)。对于
分页
而言,前
和后
是基于
gameId
的参数<如果值为
null
或大于
5
,则代码>限制将默认为
5
。在前面提到的结果中附加的最佳方式是什么

例如,
http://localhost:3000/api/Categories/1004/games/mature?before=1000053
将返回所有
gameId
小于
1000053
之前的
所有
gameId
大于
1000053

通用/models/category.js

/Categories/1004/games/mature

{
      “perPage”: 5, //value from limit
      “total”: 5, //total of return items from array
      "data": [
         ... Endpoint data is here
      ],
      "paging": {
        "cursors": {
          "after": 1000057, //last item in array
          "before": 1000053 //first item in array
        },
        "previous": "http://localhost:3000/api/Categories/1004/games/mature?before=1000053" //url for previous
        "next": "http://localhost:3000/api/Categories/1004/games/mature?after=1000057" //url for after
      }
  }

这里的问题是,您使用的是类别模型作为入口点,而您似乎应该使用游戏模型的内置查询方法,带有过滤器、限制和偏移、句号。这将允许您分页,而无需添加所有这些复杂性来支持您的前后概念。没必要。如果您的关系设置正确,您只需在游戏上分页即可查询游戏模型

例如,看起来您需要一个特定类别中成熟的分页游戏列表,对吗?要使用这些条件获得5个游戏的结果,您需要发送一个json REST API调用,如下所示:

http://0.0.0.0:3000/api/Games?filter=%7B%20%22where%22%3A%20%7B%22mature%22%3Atrue%2C%20%22categoryId%22%3A%201004%7D%2C%20%22offset%22%3A%200%2C%20%22limit%22%3A%205%20%7D
{ "where": {"mature":true, "categoryId": 1004}, "offset": 0, "limit": 5 }
这很难读取,因为它是经过编码的,但底层过滤器的构造如下:

http://0.0.0.0:3000/api/Games?filter=%7B%20%22where%22%3A%20%7B%22mature%22%3Atrue%2C%20%22categoryId%22%3A%201004%7D%2C%20%22offset%22%3A%200%2C%20%22limit%22%3A%205%20%7D
{ "where": {"mature":true, "categoryId": 1004}, "offset": 0, "limit": 5 }
这将返回以下数据集,这是1004类别中的前5款游戏,也是成熟的游戏:

[
  {
    "mature": true,
    "gameName": "CODBlacOps3",
    "categoryId": 1004,
    "gameId": 1000053,
    "description": "Published by Activision",
    "publishedDate": "2015-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Evolve",
    "categoryId": 1004,
    "gameId": 1000054,
    "description": "Published by Turtle Rock Studios",
    "publishedDate": "2015-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Battlefield4",
    "categoryId": 1004,
    "gameId": 1000055,
    "description": "Published by EA Digital Illusions",
    "publishedDate": "2013-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Rainbow6",
    "categoryId": 1004,
    "gameId": 1000056,
    "description": "Published by EUbisoft",
    "publishedDate": "2015-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Destiny",
    "categoryId": 1004,
    "gameId": 1000057,
    "description": "Published by Bungie",
    "publishedDate": "2014-01-01T00:00:00.000Z"
  }
]
要获得5个游戏的下一页,我们只需将偏移量更改为5,这会告诉数据库跳过前5个,因为我们现在在第2页:

{ "where": {"mature":true, "categoryId": 1004}, "offset": 5, "limit": 5 }
这将返回以下结果:

[
  {
    "mature": true,
    "gameName": "Wolfenstein",
    "categoryId": 1004,
    "gameId": 1000058,
    "description": "Published by Bethesda",
    "publishedDate": "2014-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "StarWarsBattleFront",
    "categoryId": 1004,
    "gameId": 1000059,
    "description": "Published by EA DICE",
    "publishedDate": "2015-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Test1",
    "categoryId": 1004,
    "gameId": 1000060,
    "description": "Published by Test1",
    "publishedDate": "2015-12-19T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Test2",
    "categoryId": 1004,
    "gameId": 1000061,
    "description": "Published by Test2",
    "publishedDate": "2015-12-19T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Test3",
    "categoryId": 1004,
    "gameId": 1000062,
    "description": "Published by Test3",
    "publishedDate": "2015-12-19T00:00:00.000Z"
  }
]
默认情况下,游戏按其游戏id的顺序进行。没有自定义的远程方法和嵌套的find()是必需的

如果您想按字母顺序排列列表,还可以添加
顺序
过滤器,并将其设置为
“顺序”:“gameName ASC”

这将返回一个新的游戏数组(第1页,因为我将偏移量设置为0),按
gameName
的字母顺序排列:

[
  {
    "mature": true,
    "gameName": "Battlefield4",
    "categoryId": 1004,
    "gameId": 1000055,
    "description": "Published by EA Digital Illusions",
    "publishedDate": "2013-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "CODBlacOps3",
    "categoryId": 1004,
    "gameId": 1000053,
    "description": "Published by Activision",
    "publishedDate": "2015-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Destiny",
    "categoryId": 1004,
    "gameId": 1000057,
    "description": "Published by Bungie",
    "publishedDate": "2014-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Evolve",
    "categoryId": 1004,
    "gameId": 1000054,
    "description": "Published by Turtle Rock Studios",
    "publishedDate": "2015-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Rainbow6",
    "categoryId": 1004,
    "gameId": 1000056,
    "description": "Published by EUbisoft",
    "publishedDate": "2015-01-01T00:00:00.000Z"
  }
]
我能够如此快速地得到这个结果的方法是使用API资源管理器。我完成了你的项目,更改了数据库连接值以匹配我的本地服务器,启动了它,然后转到
http://0.0.0.0/explorer/#!/游戏/游戏\u查找
,然后在游戏模型上使用不同的
过滤器
值进行游戏:


这里的问题是,您使用的是类别模型作为入口点,而您似乎应该使用游戏模型的内置查询方法,带有过滤器、限制和偏移、句号。这将允许您分页,而无需添加所有这些复杂性来支持您的前后概念。没必要。如果您的关系设置正确,您只需在游戏上分页即可查询游戏模型

例如,看起来您需要一个特定类别中成熟的分页游戏列表,对吗?要使用这些条件获得5个游戏的结果,您需要发送一个json REST API调用,如下所示:

http://0.0.0.0:3000/api/Games?filter=%7B%20%22where%22%3A%20%7B%22mature%22%3Atrue%2C%20%22categoryId%22%3A%201004%7D%2C%20%22offset%22%3A%200%2C%20%22limit%22%3A%205%20%7D
{ "where": {"mature":true, "categoryId": 1004}, "offset": 0, "limit": 5 }
这很难读取,因为它是经过编码的,但底层过滤器的构造如下:

http://0.0.0.0:3000/api/Games?filter=%7B%20%22where%22%3A%20%7B%22mature%22%3Atrue%2C%20%22categoryId%22%3A%201004%7D%2C%20%22offset%22%3A%200%2C%20%22limit%22%3A%205%20%7D
{ "where": {"mature":true, "categoryId": 1004}, "offset": 0, "limit": 5 }
这将返回以下数据集,这是1004类别中的前5款游戏,也是成熟的游戏:

[
  {
    "mature": true,
    "gameName": "CODBlacOps3",
    "categoryId": 1004,
    "gameId": 1000053,
    "description": "Published by Activision",
    "publishedDate": "2015-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Evolve",
    "categoryId": 1004,
    "gameId": 1000054,
    "description": "Published by Turtle Rock Studios",
    "publishedDate": "2015-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Battlefield4",
    "categoryId": 1004,
    "gameId": 1000055,
    "description": "Published by EA Digital Illusions",
    "publishedDate": "2013-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Rainbow6",
    "categoryId": 1004,
    "gameId": 1000056,
    "description": "Published by EUbisoft",
    "publishedDate": "2015-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Destiny",
    "categoryId": 1004,
    "gameId": 1000057,
    "description": "Published by Bungie",
    "publishedDate": "2014-01-01T00:00:00.000Z"
  }
]
要获得5个游戏的下一页,我们只需将偏移量更改为5,这会告诉数据库跳过前5个,因为我们现在在第2页:

{ "where": {"mature":true, "categoryId": 1004}, "offset": 5, "limit": 5 }
这将返回以下结果:

[
  {
    "mature": true,
    "gameName": "Wolfenstein",
    "categoryId": 1004,
    "gameId": 1000058,
    "description": "Published by Bethesda",
    "publishedDate": "2014-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "StarWarsBattleFront",
    "categoryId": 1004,
    "gameId": 1000059,
    "description": "Published by EA DICE",
    "publishedDate": "2015-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Test1",
    "categoryId": 1004,
    "gameId": 1000060,
    "description": "Published by Test1",
    "publishedDate": "2015-12-19T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Test2",
    "categoryId": 1004,
    "gameId": 1000061,
    "description": "Published by Test2",
    "publishedDate": "2015-12-19T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Test3",
    "categoryId": 1004,
    "gameId": 1000062,
    "description": "Published by Test3",
    "publishedDate": "2015-12-19T00:00:00.000Z"
  }
]
默认情况下,游戏按其游戏id的顺序进行。没有自定义的远程方法和嵌套的find()是必需的

如果您想按字母顺序排列列表,还可以添加
顺序
过滤器,并将其设置为
“顺序”:“gameName ASC”

这将返回一个新的游戏数组(第1页,因为我将偏移量设置为0),按
gameName
的字母顺序排列:

[
  {
    "mature": true,
    "gameName": "Battlefield4",
    "categoryId": 1004,
    "gameId": 1000055,
    "description": "Published by EA Digital Illusions",
    "publishedDate": "2013-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "CODBlacOps3",
    "categoryId": 1004,
    "gameId": 1000053,
    "description": "Published by Activision",
    "publishedDate": "2015-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Destiny",
    "categoryId": 1004,
    "gameId": 1000057,
    "description": "Published by Bungie",
    "publishedDate": "2014-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Evolve",
    "categoryId": 1004,
    "gameId": 1000054,
    "description": "Published by Turtle Rock Studios",
    "publishedDate": "2015-01-01T00:00:00.000Z"
  },
  {
    "mature": true,
    "gameName": "Rainbow6",
    "categoryId": 1004,
    "gameId": 1000056,
    "description": "Published by EUbisoft",
    "publishedDate": "2015-01-01T00:00:00.000Z"
  }
]
我能够如此快速地得到这个结果的方法是使用API资源管理器。我完成了你的项目,更改了数据库连接值以匹配我的本地服务器,启动了它,然后转到
http://0.0.0.0/explorer/#!/游戏/游戏\u查找
,然后在游戏模型上使用不同的
过滤器
值进行游戏:


要将结果添加到响应中,首先更改Category.dummer远程方法返回给对象的响应类型:

Category.remoteMethod('mature', {
  accepts: [
    {arg: 'id', type: 'number', required: true},
    {arg: 'limit',type: 'number',required: false},
    {arg: 'after',type: 'number',required: false},
    {arg: 'before',type: 'number',required: false}   
  ],
  // mixing ':id' into the rest url allows $owner to be determined and used for access control
  http: {
    path: '/:id/games/mature',
    verb: 'get'
  },
  returns: {
    arg: 'games',
    type: 'object' // will be whatever you pass back as 2nd arg to callback()
  }
});
然后,只需将您想要的值添加到新的games对象中,使用您现有的GamesAR作为
数据的值,并将limit、before和after值传递到response对象中,作为成功回调的第二个参数:

callback(null, {
  "perPage": limit,
  "total": gameArray.length,
  "data": gameArray,
  "paging": {
    "cursors": {
      "after": gameArray[gameArray.length-1].game_id, // last game_id in result
      "before": gameArray[0].game_id // first game_id in result
    },
    "previous": "http://localhost:3000/api/Categories/1004/games/mature?before=" + gameArray[0].game_id,
    "next": "http://localhost:3000/api/Categories/1004/games/mature?after=" + gameArray[gameArray.length-1].game_id
  }
})
正如我提到的多个Games.find()调用使代码过于复杂,您也不应该删除该对象的3或4个副本。您可以将对象的构造封装在逻辑中,然后使用一个callback()调用来简化远程方法的I/O管理并编写更少的代码。减少到单个Games.find()调用将使发送此结果更容易


还要注意卷曲撇号字符和制表符与空格缩进的对比(选择一个并坚持使用,不要混合),当您的代码被精心构造和组织时,这会更容易得到帮助

要将结果添加到响应中,首先更改Category.dummer远程方法返回给对象的响应类型:

Category.remoteMethod('mature', {
  accepts: [
    {arg: 'id', type: 'number', required: true},
    {arg: 'limit',type: 'number',required: false},
    {arg: 'after',type: 'number',required: false},
    {arg: 'before',type: 'number',required: false}   
  ],
  // mixing ':id' into the rest url allows $owner to be determined and used for access control
  http: {
    path: '/:id/games/mature',
    verb: 'get'
  },
  returns: {
    arg: 'games',
    type: 'object' // will be whatever you pass back as 2nd arg to callback()
  }
});
然后,只需添加您想要的值即可