简体   繁体   中英

How to use MongoDB $ne on nested object property

I have a node API which connects to a mongoDB through mongoose. I am creating an advanced results middleware that enabled selecting, filtering, sorting, pagination etc. based on a Brad Traversy course Node.js API Masterclass With Express & MongoDB .This is all good.

I am adapting the code from the course to be able to use the $ne (not equal) operator and I want to be able to get a model that is not equal to a nested property (user id) of the model. I am using this for an explore feature to see a list of things, but I don't want to show the user their own things. I am having trouble figuring out how to access the id property.

********************* UPDATE *********************

It seems all the documentation I've read recommends writing const injected like this:

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

but for some reason it is not working. I can query top level properties that are just a plain string value like this:

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

but not a property on an object. Does anyone know why? Is it because the property I want to query is an id? I've also tried:

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

which also does not work...


So the model looks like this:

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

then the actual advanced results middleware looks like this and it's the 'injected' object where I am trying to access id. In the course brad uses this syntax to use lte (/?averageCost[lte]=10000) but I do not get any results with my ne. Can anyone help me here?

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;

Answering your question about how to use $ne :

The use of $ne is as follows:

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

Into your query should be like:

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

Example here

$ne operator will return all document where the field value don't match with the given value.

As you have done, to acces the nested field is necessary use the dot notation.

Also, to ensure it works, if your schema defines _id as ObjectId maybe is necessary parse req.user.id to ObjectId .
But if in your schema is a string then should works.

So try (not tested at all):

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM