MongoDB / Express: Почему Array.includes возвращает ложь вместо истины? - PullRequest
0 голосов
/ 20 мая 2018

Я работаю над крошечным приложением, которое позволяет пользователю участвовать в опросах, но у меня возникают проблемы с проверкой, проголосовал ли текущий пользователь в опросе.Все остальное работает нормально, за исключением IIFE, которое проверяет указанное условие, как показано во включенном фрагменте кода.Действительно, я получаю 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 голосов
/ 20 мая 2018

Я думаю, вы пытаетесь сравнить ObjectId со строкой, представляющей идентификатор монго.

Это должно работать:

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));
0 голосов
/ 20 мая 2018

Скорее всего, poll.votedBy не является массивом строк идентификаторов.Если вы используете его в качестве справочного поля, то это массив объектов BSON, который не сможет использовать includes, потому что он использует алгоритм sameValueZero для сравненияценности.Если это так, тогда вы можете либо сначала преобразовать все идентификаторы в строки, либо использовать методы find и equals, чтобы найти совпадение.

Обновление: показывает пример кода

Кроме того, some обеспечит более простой способ возврата логического значения.

const hasVoted = poll.votedBy.some((voter) => voter.equals(voterId));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...