Pregunta

I have two mongoose models. Let's call one model foo and the second model bar. Bar records have a related foo record and an email address. I want my api to be passed an email address and return a list of foo records that do not have a bar record created with that email address. How would I go about doing this with mongoose?

I know I could write this query with SQL but ive been trying to learn a no sql db, hence mongo.

Here is an example. I have 2 foo records and 2 bar records:

foos:

{name:"first foo"}
{name:"second foo"}

and my bar records:

{
    email:"requestEmail@example.com,
    foo_id:first_foo._id
}

{
    email:"someOther@example.com,
    foo_id:second_foo._id
}

The request to my api would come in with email: requestEmail@example.com. In this case, I would want to return the second foo (and any other foo records) because first foo has a bar record with the email in the request.

¿Fue útil?

Solución

Its probably easiest to do that in two passes. First you should retrieve all your Bar objects and then filter your Foo objects based on them. I don't have a node.js compiler so the code my contain some errors (I can edit it later during the day, but you'll get the picture).

var findFooWOutBar = function(theEmail)
{
  Bar.find({email: theEmail}, function(err,docs)
  {
    if(err)
    {
      console.log(err);
      return
    }
    else
    {
      var barIds=[];
      docs.forEach(function(bar) //fetching all of the bars with the email
      {
        barIds.push(bar._id);//or whatever you are using as a reference 
      });

      //nin means not in
      Foo.find().nin('barRef', barIds).exec(function(err,foos)
      {
        //process your Foo results (foos) here
      }); //have not tested this, but according to the docs it should go something like this      
    }
  });

}

So basically, maybe something is not exactly right here, but you need an array of Bar ids (or other reference keys you are using) and combining it with the use of nin (not in).

Otros consejos

I think you should change your schema first. bar schema can be defined as follow:

var Schema = require('mongoose').Schema;
var barSchema = new Schema({
    email: {
        type: String,
        unique: true
    },
    fooId: {
    type: Schema.Types.ObjectId
    },
});

Now, fooSchema can be defined as follow:

var Schema = require('mongoose').Schema;
var fooSchema = new Schema({ 
    name: {
       type : String
    }   
});

Ok, we have got our schema. Now we can define model and work our way to solution.

var model = require('mongoose').model;
var foo = model('Foo', fooSchema);
var bar = model('Bar', barSchema);

function fooWithNoBar(email) {
    var conditions = {
        email: email
    }
    bar.find(conditions, function (err, data) {
        if (err) {
            console.log(err);
            return
        } else {
            var barIds = [];
            data.forEach(function (bar) {
                barIds.push(bar._id); 
            });
            conditions = {
                    _id: {
                        $nin: barIds
                    }
                }
            foo.find(conditions, function (err, data) {
                console.log("foo records that do not have a bar record created with that email address: ", data);
            });
        }
    });
}

Note: I have copied some code from Aleksandar's answer.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top