我应该在Mongoose中逐个返回一个数组或数据

时间:2017-03-19 10:04:58

标签: node.js mongodb mongoose

我有这个使用IOS创建的简单应用程序,它是一个问卷调查应用程序,每当用户点击播放时,它都会调用对node.js / express服务器的请求

enter image description here

enter image description here

从技术上讲,用户点击答案后会转到下一个问题

enter image description here

我很难使用哪种方法来获取问题/问题

  1. 一次获取所有数据并将其呈现给用户 - 这是一个数组
  2. 逐个获取数据作为用户进度,下一个问题 - 每次调用一个数据
  3. API示例

    // Fetch all the data at once
    app.get(‘/api/questions’, (req, res, next) => {
      Question.find({}, (err, questions) => {
        res.json(questions);
      });
    });
    
    // Fetch the data one by one
    app.get('/api/questions/:id', (req, res, next) => {
      Question.findOne({ _id: req.params.id }, (err, question) => {
       res.json(question);
      });
    });
    

    第一种方法的问题在于,假设有200个问题,mongodb一次获取并且可能慢于进行网络请求不会很慢

    2号方法的问题,我无法想象如何做到这一点,因为每个问题都是独立的并且触发下一个api调用只是很奇怪,除非mongodb中有一个计数器或一个级别。

    为了清楚起见,这是Mongoose中的数据库设计问题

    const mongoose = require('mongoose');
    const Schema = mongoose.Schema;
    
    const QuestionSchema = new Schema({
        question: String,
        choice_1: String,
        choice_2: String,
        choice_3: String,
        choice_4: String,
        answer: String
    });
    

4 个答案:

答案 0 :(得分:1)

非常好的问题。我想这个问题的答案取决于你对这个应用程序的未来计划。

如果您计划有500个问题,那么逐个获取这些问题将需要500个api电话。总是不是最好的选择。另一方面,如果你一次获取所有这些,它将根据每个对象的大小延迟响应。

所以我的建议是使用分页。当用户达到第8个问题时,带来10个结果,用下面的10个问题更新列表。

这是移动开发人员的常见做法,这也使您可以根据用户之前的回复灵活地更新下一个问题。就像自适应测试一样。

修改

您可以添加pageNumber&请求中的pageSize查询参数,用于从服务器获取问题,如下所示。

myquestionbank.com/api/questions?pageNumber=10&pageSize=2

在服务器上接收这些参数

var pageOptions = {
    pageNumber: req.query.pageNumber || 0,
    pageSize: req.query.pageSize || 10
}

并且在从数据库查询时提供这些附加参数。

Question.find()
    .skip(pageOptions.pageNumber * pageOptions.pageSize)
    .limit(pageOptions.pageOptions)
    .exec(function (err, questions) {
        if(err) {
        res.status(500).json(err); return; 
        };

        res.status(200).json(questions);
    })

注意:以零(0)开始你的pageNumber它不是强制性的,但这是惯例。

skip() 方法允许您跳过前n个结果。考虑第一种情况,pageNumber将为零,因此乘积(pageOptions.pageNumber * pageOptions.pageSize)将变为零,并且它不会跳过任何记录。 但是对于下一次(pageNumber = 1),产品将导致10.因此它将跳过已经处理的前10个结果。

limit() 此方法会限制将在结果中提供的记录数。

请记住,您需要为每个请求更新pageNumber变量。 (虽然你也可以改变限制,但建议在所有请求中保持相同)

因此,您所要做的就是,只要用户遇到倒数第二个问题,您就可以从服务器请求10(pageSize)更多问题,并将其放入数组中。

代码参考:here

答案 1 :(得分:1)

我会使用Dave的方法,但我会在这里详细介绍一下。 在您的应用中,创建一个包含问题的数组。然后还存储一个用户当前所在问题的值,例如将其称为index。然后,您有以下伪代码:

index = 0
questions = []

现在你有了这个,一旦用户启动应用程序,加载10个问题(参见Dave的回答,使用MongoDB的跳过并限制),然后将它们添加到数组中。向您的用户提供questions [index]服务。一旦索引达到8(=第9个问题),通过API加载10个问题,并将它们添加到数组中。这样,您将始终可以为用户提供问题。

答案 2 :(得分:0)

你可以在mongodb中使用limit和skip的概念。

当你第一次点击api时,你可以让你的限制= 20,并且每次再次使用api时,skip = 0会增加你的跳过次数。

第1次=> limit = 20,skip = 0

当您点击下一个=> limit = 20,skip = 20等等

string_agg(t2.name, ',' order by t2.name)

答案 3 :(得分:0)

你是对的,我认为第一个选项是never-to-use选项。如果没有使用或有机会不在上下文中使用,那么获取那么多数据是没用的。 你可以做的是你可以公开一个新的api电话:

app.get(‘/api/questions/getOneRandom’, (req, res, next) => {
    Question.count({}, function( err, count){
        console.log( "Number of questions:", count );
        var random = Math.ceil(Math.random() * count);
        // random now contains a simple var
        now you can do
        Question.find({},{},{limit:1,skip:random}, (err, questions) => {
            res.json(questions);
        });
    })

});

skip:random将确保每次提取随机问题。这只是如何从所有问题中获取随机问题的基本概念。您可以进一步提供逻辑,以确保用户没有得到他在之前步骤中已经解决的任何问题。

希望这会有所帮助:)