3

I have these two simplified schema which I'd like to "join" based on ip address.

var personSchema = Schema({
  name: String,
  ip: String
});

var logSchema = Schema({
  message: String,
  ip: String
});

It would work if person._id was the ip address. But it's not an options for me.

Currently I've solved the problem the way that when new log is saved, I search the person and add reference to log. Schema is then like this:

var logSchema = Schema({
  message: String,
  ip: String,
  person: { type: Schema.Types.ObjectId, ref: 'Person' }
});

I've read mongoose Populate documentation, Document#populated and Model.populate(). I'm still not sure if it is possible or not. This example is very simplified, I use mapReduce and grouping on log collection and therefore population would be great for me.

I've also read Database references and it seems to me that the only option is to populate based on _id. But it's pure mongodb and maybe there is another possiblity using mongoose?

Is it possible to populate query not based on _id field?

Mr.Pohoda
  • 494
  • 8
  • 19

2 Answers2

1

MongoDB does not support joins. So .populate just makes another query, therefore the best solution for you is to make another query manually.

freakish
  • 54,167
  • 9
  • 132
  • 169
  • Do you think that it's better to make another query then to save person reference within each log record? – Mr.Pohoda Apr 02 '13 at 14:55
  • @Mr.Pohoda It doesn't really help you, since you still have to make a seperate query (`.populate` does it for you). And it will be harder to maintain such db structure. Maybe I wasn't clear enough: make a seperate query **instead of** using `.populate`. – freakish Apr 02 '13 at 14:59
  • why does populate use less memory then findOne? I just queried 200,000 entries(larger makes easier to see difference) and my mongod process when using populate never goes over 23% however when I use the findOne property it hits almost 100% of cpu allowed? – Snymax Jun 12 '15 at 21:23
  • Mongo 3.2 does support the aggregate $lookup which is much like a join – Lotus Mar 15 '16 at 20:53
1

MongoDB 3.2 introduces a $lookup aggregate. You can use this with mongoose also. This is an example of how to use it with a conditional find also:

  Log.aggregate(
      { $match: {log_property: 'value'}},
      { $lookup: {from: 'person', localField: 'ip', foreignField: 'ip', as: 'user'} }
    ).exec( function (err, logs) {
      if (err) {
        next(err);
      }

      res.json(logs);
    }
  );

In the above example, the user property on each log will be filled in with the person from the matching Person model document

Lotus
  • 2,596
  • 1
  • 22
  • 20