2013-08-14 30 views
16

Tôi có schema tài liệu sau đây:Thêm các biến 'ảo' vào lược đồ mongoose?

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

Bây giờ, trong ứng dụng của tôi, tôi muốn cũng phải có nguồn html của trang bên trong đối tượng, nhưng tôi không muốn để lưu trữ nó trong db.

Tôi có nên tạo đối tượng nâng cao "cục bộ" có tham chiếu đến tài liệu db không?

function Page (docModel, html) { 
    this._docModel = docModel 
    this._html = html 
} 

Có cách nào để sử dụng mô hình tài liệu trực tiếp bằng cách thêm trường "ảo" không?

+0

Tại sao bạn muốn có nó trong đối tượng nhưng không lưu trữ? –

+0

Bởi vì tôi không cần nó liên tục: nếu tôi khởi động lại máy chủ của tôi và tải lại các đối tượng từ cơ sở dữ liệu, html đó sẽ cần phải được cập nhật quá (nó đến từ một quá trình bên ngoài). Tôi có thể cất giữ nó, nhưng nó sẽ lãng phí không gian. Vì trong Mongoose có những phương pháp ảo, nó sẽ được tốt đẹp để còn có các biến ảo .. – fusio

+1

Bạn chỉ có thể thiết lập [chết tiệt nhập] một tài sản trên các đối tượng như 'document.prop = html'. Tôi không nghĩ rằng phương pháp đó hoặc virtuals sẽ thực sự cho phép bạn lấy dữ liệu "địa phương" nếu bạn lấy đối tượng từ db nữa tuy nhiên, ngay cả khi không khởi động lại. –

Trả lời

32

Điều này là hoàn toàn có thể trong mongoose.
Kiểm tra ví dụ này, lấy từ tài liệu của họ:

var personSchema = new Schema({ 
    name: { 
    first: String, 
    last: String 
    } 
}); 

personSchema.virtual('name.full').get(function() { 
    return this.name.first + ' ' + this.name.last; 
}); 
console.log('%s is insane', bad.name.full); // Walter White is insane 

Trong ví dụ trên, bất động sản sẽ không có một setter. Để có một setter cho ảo này, làm điều này:

personSchema.virtual('name.full').get(function() { 
    return this.name.full; 
}).set(function(name) { 
    var split = name.split(' '); 
    this.name.first = split[0]; 
    this.name.last = split[1]; 
}); 

Documentation

+2

Có nhưng họ không thêm các trường mới .. Chúng đang sử dụng các trường hiện có. – fusio

+1

Và vấn đề là gì? Bạn cũng có thể sử dụng setters. – gustavohenke

+0

oh, tôi hiểu rồi. bạn có nghĩa là tôi nên 'this.newfield =' bên trong tập 'ảo'. – fusio

11

tôi đã không thực sự thử nghiệm này nhưng ý tưởng dường như xứng đáng:

//model 
var pageSchema = new Schema({ 
     name: String 
    , desc: String 
    , url: String 
}) 

pageSchema.virtual('html') 
    .get(function(){ 
    var url = this.url 

    function get(url) { 
     return new (require('httpclient').HttpClient)({ 
     method: 'GET', 
      url: url 
     }).finish().body.read().decodeToString(); 
    } 

    return get(url); 
    }); 


    //controller 
    var page = new Page({ 
    name: "Google" 
    , desc: "Search engine" 
    , url: "http://google.com" 
    }); 

    var html = page.html; 

Về cơ bản thiết lập một thuộc tính ảo gọi html mà yêu cầu cơ thể cho thuộc tính url và trả về nó.

Đảm bảo bật xuất các thuộc tính ảo cho toJSON nếu bạn đang sử dụng express và res.send(page).

pageSchema.set('toJSON', { 
    virtuals: true 
}); 
12

tin tài liệu bắt đầu bằng __ không tồn vào db, vì vậy bạn có thể tạo ra một tài sản ảo và có getter và sử dụng setter this.__html

pageSchema.virtual('html').get(function() { 
    return this.__html; 
}).set(function (html) { 
    this.__html = html; 
}); 

nhưng đây là một chút của một hack với một caveat: chức năng này không được ghi nhận như vậy không có danh sách các thuộc tính nội bộ mà bắt đầu với __ do đó là một khả năng, mặc dù khó xảy ra, rằng trong tương lai việc thực hiện nội bộ có thể bắt đầu sử dụng một var gọi __html

https://github.com/Automattic/mongoose/issues/2642

Các vấn đề liên quan