2011-12-17 21 views
17

Używam MongoDB jako strażnika dziennika dla mojej aplikacji, aby następnie zsynchronizować klientów mobilnych. Mam ten model ustanowione w NodeJS:Mongoose: Wypełnij zaludnione pole

var UserArticle = new Schema({ 
    date: { type: Number, default: Math.round((new Date()).getTime()/1000) }, //Timestamp! 
    user: [{type: Schema.ObjectId, ref: "User"}], 
    article: [{type: Schema.ObjectId, ref: "Article"}], 
    place: Number,  
    read: Number,  
    starred: Number, 
    source: String 
}); 
mongoose.model("UserArticle",UserArticle); 

var Log = new Schema({ 
    user: [{type: Schema.ObjectId, ref: "User"}], 
    action: Number, // O => Insert, 1 => Update, 2 => Delete 
    uarticle: [{type: Schema.ObjectId, ref: "UserArticle"}], 
    timestamp: { type: Number, default: Math.round((new Date()).getTime()/1000) } 
}); 
mongoose.model("Log",Log);

Kiedy chcę sprowadzaniu dziennik użyć kodu follwing:


var log = mongoose.model('Log'); 
log 
.where("user", req.session.user) 
.desc("timestamp") 
.populate("uarticle") 
.populate("uarticle.article") 
.run(function (err, articles) { 
if (err) { 
    console.log(err); 
     res.send(500); 
    return; 
} 
res.json(articles); 

Jak widać, chcę mangusta, aby wypełnić „uarticle” pole z kolekcji Log, a następnie chcę wypełnić pole "article" w UserArticle ("uarticle").

Ale używając tego kodu, Mongoose wypełnia tylko "uarticle" przy użyciu UserArticle Model, ale nie jest to pole artykułu wewnątrz uarticle.

Czy można to zrobić za pomocą mangusty i wypełnienia() lub powinienem zrobić coś innego?

Dziękuję

+0

Zabrakło mi na ten sam problem, gdzie odwołanie jest osadzony w tablica -> myList: [{mid: {type: Schema.ObjectId, 'ref': 'OtherModel'}, meta: [String]}]. Tworzy następujący błąd, gdy próbuję .populate ("myList.mid") ... TypeError: Nie można wywołać metody "ścieżka" o niezdefiniowanym – Greg

Odpowiedz

16

Z tego co sprawdziłem w dokumentacji iz tego co słyszę od ciebie, to nie może być osiągnięty, ale można wypełnić „uarticle.article” Dokumenty siebie w funkcji zwrotnej.

Chciałbym jednak zwrócić uwagę na inny aspekt, który uważam za ważniejszy. Masz dokumenty w zbiorze A, którego kolekcja odniesienia B, oraz w dokumentach kolekcji B masz inne odniesienia do dokumentów w kolekcji C.

Robisz to źle (mam na myśli strukturę bazy danych), lub powinieneś używać relacyjnej bazy danych, takiej jak MySQL. Potencjał MongoDB polega na tym, że możesz osadzić więcej informacji w dokumentach, tym samym zmuszając do mniejszych zapytań (mając swoje dane w jednej kolekcji). Odwołanie się do czegoś jest w porządku, posiadanie referencji, a następnie innego odniesienia nie wygląda na to, że w pełni czerpiecie korzyści z MongoDB.

Być może chcesz podzielić się swoją sytuacją i strukturą bazy danych, abyśmy mogli Ci pomóc.

+0

Kolekcja Logs jest jedyną, która ma dziwne odniesienia, po prostu chciałem, ponieważ inni mieć tylko 1 referencję (aby uniknąć wielokrotnego powtarzania tych samych danych). Myślę, że aby uniknąć użycia wielu informacji, nie będę wypełniać tego "uarticle", a klient złoży wniosek o szczegółowe informacje na temat artykułu, aby zachować prostotę i szybkość. – Francesc

+1

Czy możesz podać więcej szczegółów na temat swojej odpowiedzi - czy dobrze czytam, że należy zbadać nawet jedno odniesienie. Właśnie zaczynam w mongodbie. W końcu wiele tabel relacyjnych ma tylko jeden klucz obcy. Czy dokumenty osadzone lepiej nadają się do wypełniania obiektów ObjectId? – grantwparks

+0

To naprawdę zależy od struktury projektu, czasami możesz nawet chcieć zduplikować dane (osadzić) dla szybkości, innym razem prawdopodobnie będziesz musiał się do niej odnieść, ponieważ dane będą sprawdzane tylko w określonych warunkach. – alessioalex

0

jak o coś takiego:

populate_deep = function(type, instance, complete, seen) 
{ 
    if (!seen) 
    seen = {}; 
    if (seen[instance._id]) 
    { 
    complete(); 
    return; 
    } 
    seen[instance._id] = true; 
    // use meta util to get all "references" from the schema 
    var refs = meta.get_references(meta.schema(type)); 
    if (!refs) 
    { 
    complete(); 
    return; 
    } 
    var opts = []; 
    for (var i=0; i<refs.length; i++) 
    opts.push({path: refs[i].name, model: refs[i].ref}); 
    mongoose.model(type).populate(instance, opts, function(err,o){ 
    utils.forEach(refs, function (ref, next) { 
     if (ref.is_array) 
     utils.forEach(o[ref.name], function (v, lnext) { 
      populate_deep(ref.ref_type, v, lnext, seen); 
     }, next); 
     else 
     populate_deep(ref.ref_type, o[ref.name], next, seen); 
    }, complete); 
    }); 
} 

meta utils jest szorstka ... chcą SRC?

5

Możesz użyć wtyczki mongoose-deep-populate, aby to zrobić. Użycie:

User.find({}, function (err, users) { 
    User.deepPopulate(users, 'uarticle.article', function (err, users) { 
     // now each user document includes uarticle and each uarticle includes article 
    }) 
}) 

Nota prawna: Jestem autorem wtyczki.

1

I w obliczu tego samego problemu, ale po godzinach starań znajdę solution.It może być bez użycia wtyczki zewnętrznego :)

applicantListToExport: function (query, callback) { 
     this 
     .find(query).select({'advtId': 0}) 
     .populate({ 
      path: 'influId', 
      model: 'influencer', 
      select: { '_id': 1,'user':1}, 
      populate: { 
      path: 'userid', 
      model: 'User' 
      } 
     }) 
    .populate('campaignId',{'campaignTitle':1}) 
    .exec(callback); 
    }