Как использовать MongoDB $ ne для свойства вложенного объекта

#node.js #mongodb #mongoose

#node.js #mongodb #мангуст

Вопрос:

У меня есть API узла, который подключается к MongoDB через mongoose. Я создаю промежуточное ПО для расширенных результатов, которое позволяет выбирать, фильтровать, сортировать, разбивать на страницы и т. Д. На основе курса Brad Traversy Node.js Мастер-класс по API с помощью Express и MongoDB. Это все хорошо.

Я адаптирую код из курса, чтобы иметь возможность использовать оператор $ ne (not equal), и я хочу иметь возможность получить модель, которая не равна вложенному свойству (идентификатору пользователя) модели. Я использую это для функции изучения, чтобы увидеть список вещей, но я не хочу показывать пользователю их собственные вещи. У меня возникли проблемы с пониманием того, как получить доступ к свойству id.

********************* ОБНОВИТЬ *********************

Кажется, вся документация, которую я прочитал, рекомендует писать const, введенный следующим образом:

 const injected = {
  'user._id': { "$ne": req.user.id }
};
  

но по какой-то причине он не работает. Я могу запрашивать свойства верхнего уровня, которые представляют собой простое строковое значение, подобное этому:

 const injected = {
  access: { "$ne": "public" }
};
  

но не свойство объекта. Кто-нибудь знает, почему? Это потому, что свойство, которое я хочу запросить, является идентификатором? Я также пробовал:

 const injected = {
  'user._id': { "$ne": mongoose.Types.ObjectId(req.user.id) }
};
  

который также не работает…


Итак, модель выглядит следующим образом:

 {
  name: 'Awesome post',
  access: 'public',
  user: {
    _id: '2425635463456241345', // property I want to access
  }
}
  

тогда фактическое промежуточное программное обеспечение с расширенными результатами выглядит следующим образом, и это «внедренный» объект, к которому я пытаюсь получить доступ id. В курсе брэд использует этот синтаксис для использования lte (/?averageCost [lte] = 10000), но я не получаю никаких результатов с моим ne. Кто-нибудь может мне здесь помочь?

 const advancedResults = (model, populate) => async (req, res, next) => {
  let query;

  const injected = {
      access: 'public',
      'user._id[ne]': req.user.id,  // I don't think user._id[ne] is correct
    };
  }

  // Copy req.query
  const reqQuery = { ...req.query, ...injected };

  console.log('injected: ', injected);


  // Fields to exclude
  const removeFields = ['select', 'sort', 'page', 'limit'];

  // Loop over removeFields and delete them from reqQuery
  removeFields.forEach(param => delete reqQuery[param]);

  // Create query string
  let queryStr = JSON.stringify(reqQuery);

  // Create operators ($gt, $gte, etc)
  queryStr = queryStr.replace(/b(gt|gte|lt|lte|in|ne)b/g, match => `$${match}`);


  // Finding resource and remove version
  query = model.find(JSON.parse(queryStr)).select('-__v');

  // Select Fields
  if (req.query.select) {
    const fields = req.query.select.split(',').join(' ');
    query = query.select(fields);
  }

  // Sort
  if (req.query.sort) {
    const sortBy = req.query.sort.split(',').join(' ');
    query = query.sort(sortBy);
  } else {
    query = query.sort('-createdAt');
  }

  // Pagination
  const page = parseInt(req.query.page, 10) || 1;
  const limit = parseInt(req.query.limit, 10) || 25;
  const startIndex = (page - 1) * limit;
  const endIndex = page * limit;
  const total = await model.countDocuments(JSON.parse(queryStr));

  query = query.skip(startIndex).limit(limit);

  if (populate) {
    query = query.populate(populate);
  }

  // Executing query
  const results = await query;

  // Pagination result
  const pagination = {};

  if (endIndex < total) {
    pagination.next = {
      page: page   1,
      limit,
    };
  }

  if (startIndex > 0) {
    pagination.prev = {
      page: page - 1,
      limit,
    };
  }

  res.advancedResults = {
    success: true,
    count: results.length,
    pagination,
    data: results,
  };

  next();
};

module.exports = advancedResults;
  

Ответ №1:

Отвечая на ваш вопрос о том, как использовать $ne :

Использование $ne заключается в следующем:

 "field":{
  "$ne": yourValue
}
  

В вашем запросе должно быть:

 "user._id": {
  "$ne": req.user.id
}
  

Пример здесь

$ne оператор вернет весь документ, в котором значение поля не совпадает с заданным значением.

Как вы уже сделали, для доступа к вложенному полю необходимо использовать точечную нотацию.

Кроме того, чтобы убедиться, что это работает, если ваша схема определяет _id как ObjectId , возможно, необходимо проанализировать req.user.id ObjectId .
Но если в вашей схеме есть строка, то она должна работать.

Так что попробуйте (вообще не тестировалось):

 const injected = {
  'user._id': { "$ne": req.user.id }
};
  

Комментарии:

1. Привет, спасибо! Похоже, это не работает; Я все еще получаю результаты от вошедшего в систему пользователя. Я также пытался заменить req.user.id с жестко закодированной строкой.

2. Я также пробовал это так: ‘user._id’: { ne: новый мангуст. Типы. ObjectId(req.user.id ) }, но безуспешно. (Я удалил $ из ne, потому что, если вы заметили, мой код добавит это позже.

3. Можете ли вы опубликовать свой req объект?

4. Весь запрос или только запрос? Консольный журнал запроса после создания операторов выдает (идентификатор здесь поддельный): queryStr: {«access»:»public»,»user._id»: {«$ne»:»5t845tu495t83r3iuf3rf»}}

5. Ваш запрос ищет access:"public" , но в вашей модели есть только поля name и user . Я использовал name:"Awesome post" вместо "access":"public" , и это работает. Если ваши данные или ваша модель изменились, отредактируйте OP, и я снова выполню.