Mongoose - find objects which are NOT IN another list of objects

不打扰是莪最后的温柔 提交于 2019-12-13 03:48:57

问题


A few days ago I posted this question. Since I didn't find a working solution, I've changed my app's structure a bit and that's why I'm posting this new question.

There are User and Task models. A User contains two lists of Tasks, and those are tasksAssigned and tasksCompleted:

user.model.js

const mongoose = require("mongoose");
const autopopulate = require("mongoose-autopopulate");
const UserSchema = mongoose.Schema({
  username: String,
  password: String,
  firstName: String,
  lastName: String,
  friends: [
    { type: mongoose.Schema.ObjectId, ref: "User", autopopulate: true }
  ],
  tasksAssigned: [
    { type: mongoose.Schema.ObjectId, ref: "Task", autopopulate: true }
  ],
  tasksCompleted: [
    { type: mongoose.Schema.ObjectId, ref: "Task", autopopulate: true }
  ]
  // TODO: When saving, use something like this: peter.subjects.push(math._id, computer._id)
});
UserSchema.plugin(autopopulate);
module.exports = mongoose.model("User", UserSchema);

task.model.js

const mongoose = require("mongoose");
const autopopulate = require("mongoose-autopopulate");    
const TaskSchema = mongoose.Schema({
  name: String,
  type: String,
  percentage: Number
});
TaskSchema.plugin(autopopulate);    
module.exports = mongoose.model("Task", TaskSchema);

I need to find a list of Tasks which are not assigned to a particular User. In the frontend application I have task.service.js with a method:

function getAllUserTasksNotAssignedToUser(userId) {
  $http
    .get("http://localhost:3333/tasks/notAssignedToUser/" + userId)
    .then(function(response) {
      return response.data;
    });
}

On the backend, there is task.routes.js, where this route is defined:

app.get("/tasks/notAssignedToUser/:userId", tasks.findAllNotAssignedToUser);

...and in task.controller.js there is a relevant method:

exports.findAllNotAssignedToUser = (req, res) => {
  console.log("Back controller call");
  User.findById(req.params.userId)
    .then(user => {
      Task.find({ _id: {$nin: user.tasksAssigned }}).then(tasks => {
        res.send(tasks);
      });
    })
    .catch(err => {
      res.status(500).send({
        message:
          err.message ||
          "Some error occurred while retrieving tasks not assigned to the user."
      });
    });
};

As you can see, my idea was to find a particular User first, and then all the Tasks which are not in that User's tasksAssigned list. However, something went wrong and in browser's console I get:

TypeError: Cannot read property 'then' of undefined
    at new AdminUserDetailsController (bundle.js:38254)
    at Object.instantiate (bundle.js:6395)
    at $controller (bundle.js:12447)
    at Object.link (bundle.js:1247)
    at bundle.js:2636
    at invokeLinkFn (bundle.js:11994)
    at nodeLinkFn (bundle.js:11371)
    at compositeLinkFn (bundle.js:10642)
    at publicLinkFn (bundle.js:10507)
    at lazyCompilation (bundle.js:10898) "<div ng-view="" class="ng-scope">"

What would be the right way to implement this?


回答1:


I created your schemas and populate with some fake data:

  let task1 = new Task({
    name: 'task1',
    type: 'type1',
    percentage: '10'
  });
  task1.save();
  let task2 = new Task({
    name: 'task2',
    type: 'type2',
    percentage: '20'
  });
  task2.save();
  let task3 = new Task({
    name: 'task3',
    type: 'type3',
    percentage: '30'
  });
  task3.save();

I added two tasks(task1 and task3) for this user in the field tasksAssigned:

let user1 = new User({
    username: 'name teste',
      password: '123456',
    firstName: 'first name test',
    lastName: 'last name test',
    friends: [],
    tasksAssigned: ['5b579e94454cb206f6ca338f','5b579e94454cb206f6ca3391'],
    tasksCompleted: []});
  user1.save();

And executed your code. After that I found only one problem, when you call Task.find you need to check if the user was found, if you don't check you will receive a error in the user.tasksAssigned line.

User.findById('5b579ee41ac34e0763324fe3')
    .then(user => {
      if(user) {
        Task.find({_id: {$nin: user.tasksAssigned}}).then(tasks => {
          console.log(tasks);
          res.send(tasks);
        });
      }
    })
    .catch(err => {
      console.log('error');
      console.log(err);
      res.status(500).send({
        message:
        err.message ||
        "Some error occurred while retrieving tasks not assigned to the user."
      });
    });

This is the console log inside the Task then method:

Here the result of the route in the browser:

In this link you can see the Mongoose documentation about promises: Mongoose Promises



来源:https://stackoverflow.com/questions/51486752/mongoose-find-objects-which-are-not-in-another-list-of-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!