MongoDB及其在Meteor中的工作原理(数组、变量)

MongoDB及其在Meteor中的工作原理(数组、变量),mongodb,meteor,Mongodb,Meteor,我正在创建一个关于Meteor的测验应用程序。因此,在我的一个助手函数中,我创建了一个包含来自数据库中不同文档的所有ID的数组(所有ID都等于不同的问题+答案),并将其设置为一个变量 var queue = Quiz.find().fetch(); for(var i = 1; i < queue.length; i++){ if(queue[i]){ result = queue[i]._id; break;

我正在创建一个关于Meteor的测验应用程序。因此,在我的一个助手函数中,我创建了一个包含来自数据库中不同文档的所有ID的数组(所有ID都等于不同的问题+答案),并将其设置为一个变量

var queue = Quiz.find().fetch();
      for(var i = 1; i < queue.length; i++){
        if(queue[i]){
          result = queue[i]._id;
          break;
        }

      }

      Router.go("question", {_id: result});
var queue=quick.find().fetch();
对于(变量i=1;i
我想要完成的是,我希望路由器在循环的每次迭代后都能收到一个新的id。因此,每次用户回答一个问题后,我希望出现一个新的id,以便用户得到一个新问题,而不是旧问题

我正在考虑使用.pop()方法,显示数组的最后一个_id并将其从数组中删除


我的问题是,使用.pop()是否会从数据库中完全删除该条目?当我现在写这篇文章时,我想会的,因为游标是反应式的。有没有办法解决这个问题?

我将尝试构建问题的结构:

  • 您向客户提供一个(随机)数字列表,每个数字都是一个问题ID
  • 您需要在用户发起的某些事件上操作此列表
  • 您需要维护与此列表对应的应用程序状态
  • 您需要根据列表中的某些(头)元素显示不同的内容
  • 实际上,操作集合比将任意数字映射到集合的条目更容易。因此,工作流程略有变化:

  • 您向客户机提供一个集合,以某种方式进行排序和缩减
  • 客户机应该记住公开集合的某些(头)元素
  • 它应该根据公开集合的元素呈现相应的DOM
  • 现在,一步一步

    公开收藏 假设您有一个收藏:

    Quiz = new Mongo.Collection('quiz');
    
    Quiz.insert({
        published: true,
        question: 'The tallest waterfall on the planet',
        answers: [{
            id: 'A',
            label: 'Niagara Falls'
        }, {
            id: 'B',
            label: 'Angel Falls'
        }, {
            id: 'C',
            label: 'Victoria Falls'
        }],
        correct: 'B'
    });
    
    接下来要做的是将其发布到服务器上:

    Meteor.publish('quiz', function () {
        return Quiz.find({
            published: true // this will filter out all the "unpublished" questions if there are any
        }, {
            fields: {
                correct: 0 // this will filter out the field so it doesn't appear on client
            }
        });
    });
    
    并在客户端上订阅:

    Meteor.subscribe('quiz');
    
    从现在起,每次在客户端上对
    quick
    集合执行
    find
    findOne
    时,它只会生成忽略
    correct
    属性的已发布问题

    还记得国家吗 记住状态的最简单方法是将其存储在会话变量中。因此,首先,您应该设置它,然后根据用户回答是否正确更改其值:

    // Initiate questionsAnswered session variable, an array of answered questions
    var questionsAnswered = Session.get('questionsAnswered') || [];
    Session.set('questionsAnswered', questionsAnswered);
    
    // Pick a quasi-random question that hasn't been answered yet
    var question = Quiz.findOne({
        question: {
            $nin: Session.get('questionsAnswered')
        }
    });
    
    // When user answers the question
    Session.set('questionsAnswered', questionsAnswered.concat(question.question));
    
    我想我必须澄清一下

  • 会话变量
    questionsAnswered
    存储字符串数组,每个字符串实际上都是一个问题,即
    question
    集合条目的
    属性
  • 查找查询中的
    $nin
    表示“不在(列表)”并按如下方式工作:如果您有一个具有某些ID的集合
    [1、2、3、4]
    ,则“不在列表中”将返回ID不等于1、2、3或4的每个条目
  • findOne
    保证从集合中只选择一个(或零个)条目。它是
    find().fetch()[0]
    的缩写
  • concat
    ,由于会话变量存储数组,是一种
    array
    方法,它将两个数组或一个带有标量值的数组连接起来,并返回结果。或者,在这种特殊情况下,是一个字符串数组和一个字符串
  • 渲染它 现在,是渲染它的时候了。请记住,当前问题存储在局部变量
    question
    中。您可以将其放入另一个会话变量中,并从模板帮助器访问它,因此代码为:

    Session.set('currentQuestion', question);
    
    Template.theQuestion.helpers({
        question: function () {
            return Session.get('currentQuestion');
        }
    });
    
    模板可能如下所示:

    <template name="theQuestion">
        <p class="question">{{ question }}</p>
        <ul class="answers">
            {{#each answers}}
                <li class="answer">
                    <label for="{{ id }}">
                        <input type="radio" value="{{ id }}">
                        {{ label }}
                    </label>
                </li>
            {{/each}}
        </ul>
    </template>
    
    其中,
    问题
    是当前问题(集合光标的头部元素)。这将使URL表示当前问题,整个过程将一个接一个地在问题列表中移动,同时在会话变量中存储已回答问题的列表以及当前问题


    我说“当前”,但它很容易被认为是“下一个”。

    也许只需给测验集合打一个电话,就会得到一堆随机配置的测验问题。然后,您将按顺序将其保存到用户的集合中,可能是QuizTaker集合。该集合至少有用户名和一系列问题需要回答。这取决于,如果用户离开并返回您的站点,如果您将该集合存储在用户独有的服务器(MongoDB)上,然后他们可以继续离开的位置。我的意思是这个应用程序只是一次访问,参加测验,离开之类的事情。只是一个获取流星技能的项目。从本地获取的数组中弹出不会是反应。这与执行Collection.remove()操作不同啊,这样我就可以安全地弹出获取的数据,而不会有删除数据的风险?美好的我会在问之前试一下,但我不想冒险拿走任何东西。非常感谢你的明确解释。我的情况唯一的细微差别是,我的测验在每个问题之后都会加载一个“新页面”。因此,在回答一个问题后,用户单击“下一步”并加载另一个问题。我的路由器使用了:_id参数,所以我试图找出如何随机选择id,这样当它被应答时,它就会被删除,不再出现,同样的问题也不会再次出现。但你在这里是如何做到的更有意义。非常感谢。
    Router.go('question', question);