2011-12-17 37 views
17

Tôi đang sử dụng MongoDB làm trình quản lý nhật ký cho ứng dụng của mình để đồng bộ hóa ứng dụng khách di động. Tôi có các mô hình này thành lập năm NodeJS:Mongoose: Điền một trường được điền đơn

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);

Khi tôi muốn truy xuất nhật ký tôi sử dụng mã 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); 

Như bạn thấy, tôi muốn cầy mangut để cư "uarticle" trường từ bộ sưu tập Nhật ký và, sau đó, tôi muốn điền vào trường "bài viết" của UserArticle ("uarticle").

Nhưng, sử dụng mã này, Mongoose chỉ điền "uarticle" bằng Mô hình UserArticle chứ không phải trường bài viết bên trong uarticle.

Có thể thực hiện nó bằng Mongoose và điền vào() hoặc tôi nên làm điều gì đó khác?

Cảm ơn bạn,

+0

tôi đã chạy vào cùng một vấn đề mà các tài liệu tham khảo được nhúng vào trong một mảng -> myList: [{mid: {type: Schema.ObjectId, 'ref': 'OtherModel'}, meta: [String]}]. Điều này tạo ra lỗi sau khi tôi thử .populate ('myList.mid') ... TypeError: Không thể gọi phương thức 'path' của undefined – Greg

Trả lời

16

Từ những gì tôi đã kiểm tra trong tài liệu và từ những gì tôi nghe từ bạn, điều này không thể đạt được, nhưng bạn có thể di chuyển "uarticle.article" tài liệu cho mình trong hàm callback.

Tuy nhiên, tôi muốn chỉ ra một khía cạnh khác mà tôi cho là quan trọng hơn. Bạn có tài liệu trong bộ sưu tập A tham chiếu đến bộ sưu tập B và trong các tài liệu của bộ sưu tập B mà bạn có một tham chiếu khác đến tài liệu trong bộ sưu tập C.

Bạn đang làm sai (tôi đang tham khảo cấu trúc cơ sở dữ liệu), hoặc bạn nên đang sử dụng một cơ sở dữ liệu quan hệ như MySQL ở đây. Sức mạnh của MongoDB dựa vào thực tế bạn có thể nhúng thêm thông tin vào tài liệu, do đó phải thực hiện các truy vấn ít hơn (có dữ liệu của bạn trong một bộ sưu tập duy nhất). Trong khi tham khảo một cái gì đó là ok, có một tham chiếu và sau đó một tài liệu tham khảo không có vẻ như bạn đang tận dụng đầy đủ lợi thế của MongoDB ở đây.

Có thể bạn muốn chia sẻ tình huống của mình và cấu trúc cơ sở dữ liệu để chúng tôi có thể giúp bạn nhiều hơn.

+0

Bộ sưu tập Nhật ký là bộ duy nhất có tham chiếu kỳ lạ, tôi chỉ muốn, bởi vì những người khác chỉ có 1 tham chiếu (để tránh lặp lại nhiều lần cùng một dữ liệu). Tôi nghĩ rằng để tránh sử dụng rất nhiều thông tin, tôi sẽ không điền vào "uarticle" này và khách hàng sẽ thực hiện một yêu cầu để có được các chi tiết của Điều, chỉ để giữ cho mọi thứ đơn giản và nhanh chóng. – Francesc

+1

Bạn có thể cung cấp thêm chi tiết về câu trả lời của bạn không - tôi có đọc đúng không, thậm chí có một tài liệu tham khảo nên được kiểm tra. Tôi chỉ mới bắt đầu ở mongodb. Xét cho cùng, rất nhiều bảng quan hệ chỉ có một khóa ngoại. Các tài liệu nhúng có thích hợp hơn để điền vào đối tượng ObjectId không? – grantwparks

+0

Nó thực sự phụ thuộc vào cấu trúc của dự án, đôi khi bạn có thể muốn sao chép dữ liệu (nhúng) cho tốc độ, các lần khác bạn có thể cần tham khảo nó, vì dữ liệu đó sẽ được truy vấn chỉ trong một số điều kiện nhất định. – alessioalex

0

thế nào về một cái gì đó như:

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); 
    }); 
} 

utils meta là thô ... muốn src?

5

Bạn có thể sử dụng plugin mongoose-deep-populate để thực hiện việc này. Cách sử dụng:

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

Tuyên bố từ chối trách nhiệm: Tôi là tác giả của plugin.

1

tôi phải đối mặt với cùng một vấn đề, nhưng sau nhiều giờ nỗ lực tìm ra i solution.It có thể mà không sử dụng bất kỳ plugin bên ngoài :)

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); 
    } 
Các vấn đề liên quan