MongoDB / Express:为什么Array.includes返回false而不是true?

时间:2018-05-20 14:55:08

标签: javascript node.js mongodb express mongoose

我正在开发一个允许用户参与民意调查的小应用程序,但是我在查看当前用户是否已经在投票中投票时遇到了问题。其他一切正常,除了检查所述条件的IIFE,如包含的代码片段所示。实际上,我得到false而不是true我拥有的数据,即我已经在数据库中播放了样本数据,包括随机轮询,其中包含已经用户的ID数组投票。我尝试针对所述数组测试一个ID,它返回false而不是预期的true。是什么赋予了?

以下是相关摘录。

模型

import mongoose from 'mongoose';

const Schema = mongoose.Schema;

const ChoiceSchema = new Schema({
  name: { type: String },
  votes: { type: Number }
});

const PollSchema = new Schema({
  title: { type: String },
  category: { type: String },
  choices: [ChoiceSchema],
  addedBy: { type: Schema.Types.ObjectId, ref: 'User' },
  votedBy: [{ type: Schema.Types.ObjectId, ref: 'User' }]
});

const Poll = mongoose.model('Poll', PollSchema);

export default Poll;

控制器

import Poll from '../models/poll';

export default {
  fetchAllPolls: async (req, res) => {
    /*...*/
  },

  fetchSpecificPoll: async (req, res) => {
    /*...*/
  },

  voteInPoll: async (req, res) => {
    const { category, pollId } = req.params;
    const { name, choiceId, voterId } = req.body;

    try {
      const poll = await Poll.findById(pollId);
      const choice = await poll.choices.id(choiceId);

      const votedChoice = {
        name,
        votes: choice.votes + 1,
      };

      // Check if user has already voted in poll
      const hasVoted = ((votersIds, id) => votersIds.includes(id))(
        poll.votedBy,
        voterId
      );

      if (!voterId) {
        res
          .status(400)
          .json({ message: 'Sorry, you must be logged in to vote' });
      } else if (voterId && hasVoted) {
        res.status(400).json({ message: 'Sorry, you can only vote once' });
      } else {
        await choice.set(votedChoice);
        await poll.votedBy.push(voterId);
        poll.save();

        res.status(200).json({
          message: 'Thank you for voting. Find other polls at: ',
          poll,
        });
      }
    } catch (error) {
      res.status(404).json({ error: error.message });
    }
  },

  createNewPoll: async (req, res) => {
    /*...*/
  },
};

2 个答案:

答案 0 :(得分:1)

poll.votedBy很可能不是ID字符串数组。如果您将它用作参考字段,那么它是一个BSON对象数组,使用includes将失败,因为它使用sameValueZero算法来比较值。如果确实如此,那么您可以先将所有ID转换为字符串,也可以使用findequals方法查找匹配项。

更新:显示实际代码示例

此外,some将提供一种更简单的方法来返回布尔值。

const hasVoted = poll.votedBy.some((voter) => voter.equals(voterId));

答案 1 :(得分:1)

我认为您正在尝试将ObjectId与表示mongo id的String进行比较。

这应该有效:

const hasVoted = ((votersIds, id) => votersIds.findIndex((item) => item.toString() === id) !== -1)(
  poll.votedBy,
  voterId
);

const hasVoted = ((votersIds, id) => votersIds.findIndex((item) => item.equals(new ObjectId(id))) !== -1)(
  poll.votedBy,
  voterId
);

修改

正如@JasonCust建议的那样,一个更简单的形式应该是:

const hasVoted = poll.votedBy.some(voter => voter.equals(voterId));