2013-02-17 13 views
5

मैं games की अवधारणा को मॉडल करने की कोशिश कर रहा हूं जहां teamsplayers मोंगोडीबी में एक दूसरे के खिलाफ प्रतिस्पर्धा करता है।MongoDB: उप-दस्तावेज़ आईडी द्वारा कैसे खोजें?

मेरे पास दो संग्रह हैं: players और games

इस प्रकार games में एक दस्तावेज़ जैसा दिखता है।

{ 
    "_id": { "$oid": "1" }, 
    "teams": [ 
     { 
      "players": [ 
       { 
        "player": { "$oid": "2" }, 
        "score": 500, 
       }, 
       { 
        "player": { "$oid": "3" }, 
        "score": 550, 
       } 
      ] 
     }, 
     { 
      "players": [ 
       { 
        "player": { "$oid": "4" }, 
        "score": 500, 
       }, 
       { 
        "player": { "$oid": "5" }, 
        "score": 550, 
       } 
      ] 
     } 
    ] 
} 

यहां कार्य है: एक खिलाड़ी आईडी दिया गया है, जिसमें मैं इस गेम में भाग लेने वाले सभी गेम ढूंढना चाहता हूं।

मैं क्या कोशिश की है:

db.games.find({ "teams.players.player._id": "2" }) 

बहरहाल, यह कुछ भी वापस नहीं करता है। निम्नलिखित CoffeeScript क्वेरी के साथ

playerSchema = Schema 
    player: { type: Schema.ObjectId, ref: 'Player' } 
    score: { type: Number } 

teamSchema = Schema 
    players: [ playerSchema ] 

gameSchema = Schema 
    teams: [ teamSchema ] 

:

वैसे, मैं निम्नलिखित स्कीमा के साथ नेवला उपयोग कर रहा हूँ

Game.find 'teams.players.player._id': playerId 

जो किसी भी खिलाड़ी आईडी के लिए कोई परिणाम देता है।

+0

यदि आप सोचते हैं कि स्कीमा को बेहतर तरीके से डिज़ाइन किया जा सकता है, तो मुझे कुछ पॉइंटर्स भी मिलना अच्छा लगेगा! –

+0

क्या आप दो टीमों, या दो से अधिक चाहते हैं? मैं दो टीमों के लिए एक सभ्य उदाहरण दे सकता हूं लेकिन अधिक टीमें थोड़ी अधिक कठिन हैं और खोज उद्देश्यों के लिए अतिरिक्त फ़ील्ड शामिल हैं। –

+0

यह सिर्फ दो टीमें है। धन्यवाद! –

उत्तर

8

अपने दस्तावेज़ में:

"players": [ 
      { 
       "player": { "$oid": "4" }, 
       "score": 500, 
      }, 
      { 
       "player": { "$oid": "5" }, 
       "score": 550, 
      } 
     ] 

players के एम्बेडेड संग्रह में player क्षेत्र एक BSON आईडी है (यानी यह ObjectId("4e208e070347a90001000008") तरह दिखता है), इसलिए मुझे लगता है कि तुम इतनी तरह आपकी क्वेरी की संरचना करना चाहिए:

db.games.find({ "teams.players.player": ObjectId("2") }) 

नोट, मैंने _id छोड़ दिया है - बशर्ते कि एक मोंगो कंसोल में काम करता है, तो मुझे संदेह है कि कॉफी क्वेरी समान होगी (_id भाग ड्रॉप करें)।

+0

एक आकर्षण की तरह, धन्यवाद! मोंगोज़ के साथ यह और भी आसान है क्योंकि यह स्वचालित रूप से स्ट्रिंग को ऑब्जेक्ट आईडी में परिवर्तित करता है: 'Game.find' teams.players।प्लेयर ': प्लेयर आईडी –

1

मैंने इस उदाहरण को घर और दूर टीम तक सीमित करने के लिए आपकी प्रतिक्रिया का उपयोग किया। याद रखें कि मोंगो एक संबंधपरक डेटाबेस नहीं है और संबंधों का उपयोग अक्सर एक संबंधपरक डेटाबेस मानसिकता का संकेत होता है। डुप्लिकेशंस कुंजी है।

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

यह मूल विचार त्रुटि जांच (जैसे मिडलवेयर) के साथ सुधारना है, लेकिन मैं इसे आपके पास छोड़ देता हूं।

// Schemas 
var playerSchema = new Schema({ 
    name: {type: String, index: true, unique: true}, 
    games: {type: [Schema.ObjectId], ref: 'Game'} 
}); 

var gameSchema = new Schema({ 
    homeTeam: [{player: {name: String}, score: Number}] 
    awayTeam: [{player: {name: String}, score: Number}] 
}); 

// Models 
var Player = mongoose.model('Player', playerSchema); 
var Team = mongoose.model('Team', teamSchema); 
var Game = mongoose.model('Game', gameSchema); 

// Middleware 
gameSchema.post('save', function (game) { 
    var addMatchToPlayer = function(name) { 
     Player.findOne({name: name}, function(err, player) { 
      if (!err && player && player.games.indexOf(game._id) === -1) { 
       player.games.push(game._id); 
       player.save(); 
      } 
     }); 
    } 
    for (var i = 0; i < game.homeTeam.length; i++) { 
     addMatchToPlayer(game.homeTeam[i].name); 
    } 
    for (var i = 0; i < game.awayTeam.length; i++) { 
     addMatchToPlayer(game.awayTeam[i].name); 
    } 
}); 

// Queries 
Player.findOne({name: 'Roel van Uden'}).populate('games').exec(function (err, player) { 
}); 
+0

धन्यवाद आपके उत्तर के लिए बहुत कुछ! आप सही हैं, मैं निश्चित रूप से बहुत लंबे समय तक संबंधपरक डेटा के साथ काम कर रहा हूं। अभी भी दो चीजें हैं जो मुझे आपके प्रस्ताव के साथ परेशान करती हैं: 1. अन्य दस्तावेजों के संदर्भ के रूप में ऑब्जेक्ट आईडी का उपयोग करने में समस्या क्या है? नाम पर्याप्त अपरिवर्तनीय नहीं होगा, लेकिन आईडी अद्वितीय होने की गारंटी है। 2. मुझे इस विचार को पसंद नहीं है कि गेम और खिलाड़ियों के बीच संबंध डुप्लिकेट किया जाएगा। मैं वास्तव में इस तरह असंगतताओं को बनाने से डरता हूं। क्या मैं भी एसक्यूएल हूं? –

+0

1. यह महंगा है। मोंगो डीबी में कोई जॉइन नहीं है, इस प्रकार सिमुलेट करने के लिए डेटाबेस में कम से कम दो यात्रा की आवश्यकता होती है। रिकॉर्ड के ट्रिलियन के साथ, एसक्यूएल सुस्त हो जाएगा। MongoDB स्केल क्योंकि आप प्रासंगिक डेटा एम्बेड करते हैं, इस प्रकार केवल एक दस्तावेज़ खींचते हैं, अन्यथा यह एक ही चोक पॉइंट को दबाएगा। 2. हां, चूंकि मोंगो आपके डेटा से अवगत नहीं है, इसलिए यह संबंधों के बारे में नहीं जान सकता है और इसकी मान्यता और एफके अखंडता की कोई अवधारणा नहीं है। यदि आप असंगतताओं से डरते हैं, तो SQL से स्थानांतरित न करें, क्योंकि SQL वास्तव में सुविधाओं के सेट के लिए अद्भुत है। NoSQL अद्भुत गति के लिए बहुत सी सुविधा बलिदान। –

+0

Roel, स्पष्टीकरण के लिए धन्यवाद। मैं इन पहलुओं पर विचार करूंगा। क्या आपके पास कोई पठन युक्तियाँ हैं? –

संबंधित मुद्दे