2012-10-21 2 views
7

का उपयोग करके पसंद/नापसंद और रेटिंग को कैसे स्टोर करना चाहिए, मेरे पास किसी आइटम और उपयोगकर्ता के लिए स्कीमा है। मैं किसी उपयोगकर्ता को किसी आइटम को पसंद या नापसंद करने की अनुमति देना चाहता हूं और मैं आइटम और साथ ही उपयोगकर्ता पर एक रेटिंग एसोसिएशन भी स्टोर करना चाहता हूं।मुझे modeoose/mongdb में node.js

var UserSchema = new Schema({ 
    username : { type: String, required: true, index: { unique: true } 
    , likes : [{ type: Schema.ObjectId, ref: 'Item'}] 
    , dislikes : [{ type: Schema.ObjectId, ref: 'Item'}] 
    , ratings: [???] 
}); 

var ItemSchema = new Schema({ 
    name: { type: String}, 
    , likes : [{ type: Schema.ObjectId, ref: 'User'}] 
    , dislikes : [{ type: Schema.ObjectId, ref: 'User'}] 
    , ratings: [???] 
}); 

उपयोगकर्ता एक आइटम रेफरी स्टोर करता है, और आइटम उपयोगकर्ता को पसंद/नापसंद के लिए रेफरी करता है। मुझे यकीन नहीं है कि रेटिंग के रूप में रेटिंग को कैसे स्टोर किया जाए, क्योंकि मैं उपयोगकर्ता और मूल्य दोनों को रेट करना चाहता हूं।

item.ratings.forEach(function(rating){ 
    <%= rating.user.username %> gave <%= item.name %> a <%= rating.value %>. 
}); 

मैं भी आइटम एक उपयोगकर्ता रेटिंग मूल्य के साथ रेट किया है की एक सूची प्राप्त करना चाहते हैं:

user.ratings.forEach(function(rating){ 
    <%= user.username %> has rated <%= rating.item.name %> and gave it a <%= rating.value %> 
}); 

क्या करना चाहिए मेरी "ratings" जैसे स्कीमा देखो? क्या दो मूल्यों को स्टोर करना संभव है? उपयोगकर्ता ऑब्जेक्ट आईडी और रेटिंग मान (पूर्णांक) और इनमें से एक संग्रह है?

मेरी विधि के साथ दूसरी समस्या यह है कि मोंगोज़ अभी तक गहरे आबादी का समर्थन नहीं करता है, इसलिए मुझे इसके लिए मॉड्यूल का उपयोग करना होगा (https://github.com/JoshuaGross/mongoose-subpopulate) यह काफी हद तक अनियंत्रित है या इसे एक अलग तरीके से स्टोर करता है जिसमें घोंसले के एक से अधिक स्तर नहीं होंगे, इसलिए मैं अपना डेटा प्राप्त कर सकता हूं .populate()

कोई भी प्रतिक्रिया की सराहना की जाती है, क्योंकि मैं नया हूं NoSQL के लिए और शायद मैं इसे खत्म कर रहा हूँ।

उत्तर

6

जैसा कि आपने कहा था मैं करूँगा। मैं एक रेटिंग स्कीमा का प्रयोग करेंगे:

var RatingSchema = new Schema({ 
    , _user : { type: ObjectId, ref: 'User' } 
    , _item : { type: ObjectId, ref: 'Item' } 
    , value : Integer 
}); 

आप उपयोगकर्ता स्कीमा से रेटिंग उपयोग करने में सक्षम होना चाहते हैं, तो आप एक हुक जोड़ने के लिए इतना है कि कोई भी सहेजा RatingSchema user.ratings में जोड़ा जाता है के लिए होगा।

var UserSchema = new Schema({ 
    /* ... */ 
    ratings: [{ type: Schema.ObjectId, ref: 'Rating'}] 
}); 

RatingSchema.post('save', function() { 
    // push this.id to this._user.ratings 
    // save this._user 
}); 

के बारे में, है, तो आप नेवला-subpopulate हैक का उपयोग नहीं करना चाहते हैं, तो "दूसरी समस्या मैं अपने विधि के साथ देखते हैं कि नेवला अभी तक गहरी पॉप्युलेट का समर्थन नहीं करता है", मैं तुम्हें लोड हो रहा है refactor का सुझाव स्थिर मॉडलों में अपने मॉडल का। उदाहरण के लिए:

UserSchema.statics.findByIdAndDeepPopulate = function (i, cb) { 
    UserSchema.findOne(id) 
    .exec(function(err, user) { 
     if (err || !user) return cb(new Error('User not found')); 
     if (user._ratings.length == 0) return cb(null, user); 

     // Load and populate every ratings in user._ratings 
     for(var i = 0; i < user._ratings.length; i++) { 
     function(i) { 
      RatingSchema 
      .populate('_item') 
      .exec(err, function(rating) { 
       user._ratings[i] = rating; 
       if (i == user._ratings.length) return cb(null, user); 
      }); 
     }(i); 
     } 
    }); 
} 

संपादित करें: अब मैं इसके बारे में फिर से लगता है कि, क्यों बस UserSchema में एक एम्बेड दस्तावेज़ के रूप में रेटिंग संग्रहीत नहीं?

var UserSchema = new Schema({ 
    /* ... */ 
    ratings: [ RatingSchema ] 
}); 

आप तो बस इस तरह से पॉप्युलेट कर सकते हैं:

UserSchema.findOne(id) 
    .populate('ratings._item') 
    .exec(function(err, user) { 
    if (err || !user) return next(new Error('User not found')); 

    console.log(user.ratings); 
    }); 
+0

मुझे नहीं लगता कि आप इसे अभी तक मोंगोज़ में कर सकते हैं: '.populate ('rating._item') '- यही मेरा मतलब है गहरी आबादी()। – chovy

+0

हां आप यह कर सकते हैं यदि रेटिंग एक एम्बेड दस्तावेज़ है तो एक रेफरी नहीं है। मैं अपने कोड में यह सटीक कॉल कर रहा हूं। (पाठ्यक्रम के विभिन्न नामों के साथ) –

+0

यदि मैं रेटिंग का उपयोग करता हूं: [रेटिंगस्केमा] - मैं इसे कैसे पॉप्युलेट करूं? मैं रेटिंग सरणी में क्या धक्का देता हूं? मुझे रेटिंग की एक अलग सरणी चाहिए - मुझे नहीं लगता कि मैं उस उपयोगकर्ता ऑब्जेक्ट में रेटिंग को एम्बेड और ढीला करना चाहता हूं जिसे मैं खोज नहीं सकता। मैं अंततः रेटिंग करना चाहता हूं। ढूँढें ({_ item: item._id}, fn); – chovy

3

आप डबल क्रॉस को जोड़ने से बचना चाहते हैं क्योंकि इसका मतलब है दो बार के रूप में ज्यादा बनाए रखने के लिए और क्योंकि मोंगो लेनदेन का समर्थन नहीं करता यह बनाता है आधे जुड़े डेटा की संभावना जब आप उम्मीद करते हैं कि यह दोगुनी जुड़ा हुआ हो।कहा जा रहा है मैं इतना की तरह अपने स्कीमा पर पुनर्विचार: कह कर

var like = { 
    itemid: { type: Schema.ObjectId, ref: 'Item'} 
    , rating: Number 
}; 

var UserSchema = new Schema({ 
    username : { type: String, required: true, index: { unique: true } 
    , likes : [like] 
    , dislikes : [like] 
}); 
UserSchema.index({ 'likes.itemid': 1 }); 
UserSchema.index({ 'dislikes.itemid': 1 }); 
var User = db.model('User', UserSchema); 

var ItemSchema = new Schema({ 
    name: String 
}); 
var Item = db.model('Item', ItemSchema); 

आप पसंद या नापसंद जोड़ सकते हैं:

var piano = new Item({name: 'Mason & Hamlin Baby Grand Piano' }); 
var Joe = new User({ username: 'Joe_Smith' }); 
Joe.likes.push({ itemid: piano._id, rating: 10 }); 

और जब आप किसी आइटम के लिए पसंद को देखने के लिए चाहते हैं:

User.find({ 'likes.itemid': piano._id }, function(err, userLikes) { 
    ... 
}); 

और यदि उनमें से कोई भी आपको सही महसूस नहीं करता है तो आप इसके बजाय तीसरा संग्रह बना सकते हैं ...

var UserSchema = new Schema({ 
    username : { type: String, required: true, index: { unique: true } 
}); 
var User = db.model('User', UserSchema); 

var ItemSchema = new Schema({ 
    name: String 
}); 
var Item = db.model('Item', ItemSchema); 

var LikesSchema = new Schema({ 
    , userid: { type: Schema.ObjectId, ref: 'User'} 
    , itemid: { type: Schema.ObjectId, ref: 'Item'} 
    , rating: Number 
}); 
LikesSchema.index({ userid: 1, itemid: 1 }, { unique: true }); 

और इस मामले में यह नियम बनाना आसान है कि सकारात्मक रेटिंग एक जैसी है और नकारात्मक रेटिंग एक नापसंद है।