2

I have two Mongoose schemas:

var EmployeeSchema = new Schema({
    name: String,
    servicesProvided: [{
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Service'
    }]
});

var ServiceSchema = new Schema({
    name: String
});

I'm trying to find employees who provide a specified service with the service ID I send into the http request. This is my code:

Employee
  .find({
    servicesProvided: req.params.service_id
  })
  .exec(function(err, employees) {
    if (err) {
      console.log(err);
      res.send(err);
    } else {
      res.json(employees);
    }
});

The problem is that this code returns an empty array and I don't know why. I've tried a lot of things like casting the service id to mongoose.Schema.Types.ObjectId but it doesn't work.

Any idea? I'm using Mongoose 3.8.39. Thanks!

2 Answers 2

3

In your EmployeeSchema, servicesProvided is an array, to filter employees by that field you should use $in operator:

var services = [req.params.service_id];
Employee.find({
  servicesProvided: {
    $in: services
  }
}, ...
Sign up to request clarification or add additional context in comments.

8 Comments

This searches for documents inside provided array which is bad overhead.
@AndreyPopov With index or small lists It can be fairly efficient.
I agree, but still it's not needed. Today it's a small list, tomorrow it's a huge bottleneck :) If you can make it easier from the beginning - why not?
Thank you for your answer, it works properly but I'll choose the other answer if is more efficient.
Np, I agree that solution suggested by @AndreyPopov is more preferable in that concrete scenario.
|
2

I think you need $elemMatch! From docs:

{ _id: 1, results: [ { product: "abc", score: 10 }, { product: "xyz", score: 5 } ] },
{ _id: 2, results: [ { product: "abc", score: 8 }, { product: "xyz", score: 7 } ] },
{ _id: 3, results: [ { product: "abc", score: 7 }, { product: "xyz", score: 8 } ] }

Search like:

db.survey.find({ results: { $elemMatch: { product: "xyz", score: { $gte: 8 } } } })

Results in:

{ "_id" : 3, "results" : [ { "product" : "abc", "score" : 7 }, { "product" : "xyz", "score" : 8 } ] }

But since you're doing a single query condition (look at the docs again) you can replace

db.survey.find(
   { results: { $elemMatch: { product: "xyz" } } }
)

with

db.survey.find(
   { "results.product": "xyz" }
)

So in your case it should be something like:

find({
    'servicesProvided': ObjectId(req.params.service_id)
})

4 Comments

Sorry, It does not work either answers. Your first one returns an empty array and the second one returns a reference error : ObjectId is not defined. If I use mongoose.Schema.Types.Object(req.params.service_id) doesn't work either.
I don't know what's my 'first' and 'second' one, and why it's not working, as this should be the proper way (even tested it locally). Not sure what's going on at your place. You can accept the other answer if it suits your needs, but keep in mind to test it out what's going on and why this is not working. Again, check the online manual just to be sure ;)
Your first answer was: 'servicesProvided': req.params.service_id and your second one: 'servicesProvided._id': ObjectId(req.params.service_id). I'm sure that is the proper way but for some reason it doesn't work. I've read about this problem in many internet forums, maybe is a bug of a Mongoose version.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.