2013-12-19 2 views
0

У меня возникли проблемы с тем, как лучше всего реализовать это соединение/запрос в мангусте.Полевое поле Mongoose populate

var mongoose = require('mongoose'); 
var addressSchema = new mongoose.Schema{ 
        rank: Number, 
        address: String, 
        tag_name: String, 
        tag_url: String}; 

var tagSchema = new mongoose.Schema{ 
        address: String, 
        name: String, 
        url: String}; 

У меня есть куча сохраненных адресов и сохранена куча меток. В некоторых адресах есть теги, большинство - нет. Я часто обновляю адреса и теги отдельно. То, что я хочу сделать, - это запросить некоторые конкретные адреса и вернуть их как массив с заполненными полями тега (поля тега адреса пустые в базе данных).

Так, например, я хочу сделать это, не делая db-запрос для каждого адреса (101 db-запросов в примере). Я не уверен, что $ match или $ in или populate - это то, что я ищу. Код ниже не проверен и может не работать, но он должен дать вам представление о том, что я пытаюсь сделать.

var db = require('../config/dbschema'); 

// find an array of addresses 
db.addressModel.find({ rank: { $lte: 100 } }, function(err, addresses) { 
    // now fill in the tag fields and print 
    addTagField(0, addresses); 
}); 

// recursive function to fill in tag fields 
// address tag name and tag url fields are blank in the database 
function addTagField(n, addresses) { 
    if(n < addresses.length) { 
    db.tagModel.find({ address: addresses[n].address }, function(err, tag) { 
     // if find a tag with this address, fill in the fields 
     // otherwise leave blank and check next address in array 
     if(tag) { 
     addresses[n].tag_name = tag.name; 
     addresses[n].tag_url = tag.url; 
     } 
     addTagField(n+1, addresses); 
    }); 
    } else { 
    console.log(addresses); 
    } 
} 

http://mongoosejs.com/docs/api.html#aggregate_Aggregate-match http://mongoosejs.com/docs/api.html#query_Query-in http://mongoosejs.com/docs/api.html#document_Document-populate

Я хочу делать то, что делает выше с меньшим количеством запросов БД.

+0

Я не следую тому, что вы пытаетесь сделать. '$ match' - только для агрегаций. '$ in' - это когда вы хотите сопоставить несколько документов на основе списка, который вы указываете для определенного поля. – WiredPrairie

+0

Поскольку они находятся в двух разных коллекциях, вам нужно будет либо собрать адреса, либо запросить теги, либо использовать mapReduce. http://mongoosejs.com/docs/api.html#model_Model.mapReduce – EmptyArsenal

ответ

0

Я не хочу, чтобы вставлять документы. Это то, что я придумал.

db.addressModel.find({ rank: { $lte: 100 } }, function(err, addresses) { 
    if(err) return res.send(400); 
    if(!addresses) return res.send(404); 
    var addrOnlyAry = addresses.map(function(val, idx) { return val.address; }); 
    db.tagModel.find({ address: { $in: addrOnlyAry } }, {}, function(err, tags) { 
    if(err) return res.send(400); 
    if(tags.length > 0) addresses = setTagFields(addresses, tags); 
    return res.json(addresses); 
    } 
} 

function setTagFields(addresses, tags) { 
    for(var i=0; i < tags.length; i++) { 
    for(var j=0; j < addresses.length; j++) { 
     if(addresses[j].address === tags[i].address) { 
     addresses[j].tag_name = tags[i].tag; 
     addresses[j].tag_url = tags[i].url; 
     break; 
     } 
    } 
    } 
    return addresses; 
} 
1

Ваша основная проблема заключается в том, что вы не пользуетесь сопоставлением отношений Mongoose. Измените свои схемы немного, и ваша проблема будет легко решена. Вы можете сделать это следующим образом:

var tagSchema = new Schema({ 
    name: String, 
    url: String, 
}) 

var addressSchema = new Schema ({ 
    rank: Number, 
    address: String, 
    tags: [tagSchema], 
}) 

addressModel.find({rank: {$lte: 100}}, function(err, addresses) { 
    ... 
}) 

или это:

var tagSchema = new Schema({ 
    name: String, 
    url: String, 
}) 

var addressSchema = new Schema ({ 
    rank: Number, 
    address: String, 
    tags: [{type: ObjectId, ref: 'Tag'}], 
}) 

addressModel 
    .find({rank: {$lte: 100}}) 
    .populate('tags', 'name url') 
    .exec(function(err, addresses) { 
     ... 
    }) 
+0

Это не совсем так, поскольку 'tags' должен быть массивом ссылок (не встроенных документов) для' populate' для работы. – JohnnyHK

+0

Собственно, вы правы, моя ошибка, вы можете пропустить все вместе с этой схемой, я обновлю ответ. –

Смежные вопросы