2011-07-07 16 views
27

में गैर खाली दस्तावेज़ से मेल खाते हैं मैं एक संग्रह thusly संरचित है:MongoDB: सरणी

{ 
    _id: 1, 
    score: [ 
    { 
     foo: 'a', 
     bar: 0, 
     user: {user1: 0, user2: 7} 
    } 
    ] 
} 

मैं सभी दस्तावेजों कम से कम एक 'स्कोर' (स्कोर सरणी में तत्व) है खोजने की जरूरत है एक निश्चित है कि 'बार' का मूल्य और एक गैर-खाली 'उपयोगकर्ता' उप-दस्तावेज़।

यह है कि मैं क्या के साथ आया था (और यह है कि यह काम करना चाहिए लग रहा था) है:

db.col.find({score: {"$elemMatch": {bar:0, user: {"$not":{}} }}}) 

लेकिन, मैं इस त्रुटि मिलती है:

error: { "$err" : "$not cannot be empty", "code" : 13030 } 

कोई अन्य ऐसा करने के लिए तरीका है?

+0

क्या यह * बिल्कुल * यह कैसे संरचित है? थोड़ा सा लगता है। **> var doc = {score: [foo: 'a', bar: 0, उपयोगकर्ता: {user1: 0, user2: 7}]}; गुरु जुलाई 7 00:43:42 सिंटेक्स त्रुटि: गायब] तत्व सूची (खोल) के बाद: 1 ** –

+0

@ जस्टिन: आप सही हैं, सरणी के अंदर ब्रेसिज़ भूल गए हैं। – Dmitri

उत्तर

51

यह पता लगाया गया: { 'score.user': { "$gt": {} } } गैर-खाली दस्तावेज़ों से मेल खाएगा।

+0

इस मामले में, 'score.user' एक ऑब्जेक्ट है। क्या यह जांचने के लिए भी काम करेगा कि 'स्कोर', एक सरणी खाली है या नहीं? – zVictor

+4

यह हो सकता है, लेकिन सरणी के लिए आप संभवतः बेहतर उपयोग कर रहे हैं: '{foo: {$ not: {$ size: 0}}}' – Dmitri

+0

उत्कृष्ट! मैंने परीक्षण किया, और दोनों काम किया। क्या आप जानते हैं कि दूसरा विकल्प बेहतर क्यों होगा? – zVictor

0

सरणी आकारों की जांच के लिए $ आकार ऑपरेटर को देखें।

+0

मैं किसी भी सरणी के आकार की जांच नहीं कर रहा हूं। मैंने पहले ब्रेसिज़ का एक सेट छोड़ा, अब और अधिक स्पष्ट हो सकता है। दस्तावेजों/वस्तुओं के लिए एक समकक्ष ऑपरेटर काम करेगा, लेकिन ऐसा प्रतीत नहीं होता है। – Dmitri

3

मुझे यकीन नहीं है कि मैं आपकी स्कीमा को समझता हूं, लेकिन शायद सबसे आसान आगे तरीका score.user के लिए "खाली" मान नहीं होगा?

इसके बजाय जानबूझकर यदि आपके पास कोई सामग्री नहीं है तो आपके दस्तावेज़ में वह फ़ील्ड है?

तो आपकी क्वेरी कुछ की तरह हो सकता है ...

> db.test.find({ "score" : { "$elemMatch" : { bar : 0, "user" : {"$exists": true }}}}) 

यानी score.bar कि आप चाहते हैं (0 इस मामले में) में एक मूल्य की तलाश में mear अस्तित्व के लिए जाँच ($ score.user के मौजूद है, see docs) (और अगर यह एक मूल्य है, तो यह अस्तित्व में करेंगे?)

editied: उफ़ मैं $ elemMatch आप था ... याद

+1

हां, मैंने इसे इस तरह से करने का विचार किया है, मुख्य कारण यह है कि मैं एक प्रश्न पसंद करूंगा जो मौजूद नहीं है और खाली 'उपयोगकर्ता' दोनों से मेल खाता है कि व्यक्तिगत उपयोगकर्ता स्कोर हटा दिए जा सकते हैं और मुझे जांचना नहीं होगा चाहे सबडोक खाली है और हर बार हटा दिया जाना चाहिए। – Dmitri

1

आप शायद एक सहायक सरणी कि user दस्तावेज़ में उन का ट्रैक रखता है जोड़ना चाहते हैं:

{ 
    _id: 1, 
    score: [ 
    { 
     foo: 'a', 
     bar: 0, 
     users: ["user1", "user2"], 
     user: {user1: 0, user2: 7} 
    } 
    ] 
} 

तो फिर तुम नए उपयोगकर्ताओं atomically जोड़ सकते हैं :

> db.test.update({_id: 1, score: { $elemMatch: {bar: 0}}},      
... {$set: {'score.$.user.user3': 10}, $addToSet: {'score.$.users': "user3"}}) 

निकालें उपयोगकर्ताओं:

> db.test.update({_id: 1, score: { $elemMatch: {bar: 0}}}, 
... {$unset: {'score.$.user.user3': 1}, $pop: {'score.$.users': "user3"}})  

क्वेरी स्कोर रों:

> db.test.find({_id: 1, score: {$elemMatch: {bar: 0, users: {$not: {$size: 0}}}}}) 

आप जानते हैं कि केवल गैर-मौजूद उपयोगकर्ताओं जोड़ने होंगे और user दस्तावेज़ से मौजूद उपयोगकर्ताओं को दूर करने हैं, तो आप एक काउंटर के बजाय एक सरणी के लिए users को आसान बनाने में कर सकते हैं, लेकिन इसके बाद के संस्करण सख्त जान है।