2011-12-08 13 views
24

फ़ील्ड नाम में डॉट का उपयोग कैसे करें?फ़ील्ड नाम में डॉट का उपयोग कैसे करें?

मैं उदाहरण में त्रुटि देखें:

db.test2.insert({ "a.a" : "b" }) 

can't have . in field names [a.a] 
+0

के बारे में क्या '" एक \ ए "'? –

+0

'" एक \ .a "' कोई फर्क नहीं पड़ता है। स्ट्रिंग का अभी भी मूल्यांकन किया गया है "ए.ए" ' – codr

उत्तर

3

वास्तव में आप प्रश्नों में डॉट्स का उपयोग कर सकते हैं। देखें: http://www.mongodb.org/display/DOCS/Dot+Notation+%28Reaching+into+Objects%29

इस विशेष डॉट प्रतीक के कारण आप इसका नाम फ़ील्ड नामों में उपयोग नहीं कर सकते हैं। जैसे आप प्रोग्रामिंग भाषाओं में पहचानकर्ताओं में डॉट प्रतीक का उपयोग नहीं कर सकते हैं।

आप क्वेरी db.test2.find({ "a.a" : "b" }) लिख सकते हैं लेकिन यदि आप ऐसी क्वेरी लिखने में सक्षम होना चाहते हैं तो आपको अपनी वस्तु को इस तरह डालने की आवश्यकता है: db.test2.insert({"a": {"a": "b"}})। यह "a" नामक फ़ील्ड के साथ दस्तावेज़ बनाएगा जिसमें एम्बेड किए गए दस्तावेज़ के मूल्य के साथ "a" (दोबारा) नाम वाला फ़ील्ड "b" होगा।

44

आप \uff0E

db.test.insert({"field\uff0ename": "test"}) 
db.test.find({"field\uff0ename": "test"}).forEach(printjson) 
{ "_id" : ObjectId("5193c053e1cc0fd8a5ea413d"), "field.name" : "test" } 

के यूनिकोड बराबर करने के लिए अपने क्षेत्र के नाम का डॉट प्रतीकों की जगह ले सकता अधिक देखें:

  1. http://docs.mongodb.org/manual/faq/developers/#faq-dollar-sign-escaping
  2. http://docs.mongodb.org/manual/core/document/#dot-notation
+2

मैंने सोचा कि अवधि के लिए यूनिकोड" \ u002e "था। – William

+3

@ विलियम यदि आप शुद्ध यूनिकोड चार का उपयोग करते हैं तो आप सुझाव देते हैं, यह किसी भी तरह की एएससीआईआई अवधि में बदल जाता है - यह निर्दिष्ट करने का एक शानदार तरीका होगा। \ uFFOE एक "पूर्णतया पूर्ण रोक" चरित्र है, और एक गैर-ASCII चरित्र के रूप में अनदेखा किया जाएगा। एक \ u2024 "एक डॉट लीडर" चरित्र बेहतर दिख सकता है, क्योंकि इसकी अवधि सामान्य रूप से सामान्य अवधि के रूप में केंद्रित होती है। [मैंने अभी सत्यापित किया है कि ऐप्पल उत्पादों पर, 2024 चरित्र बहुत बेहतर दिखता है - वास्तविक अवधि की तरह।] –

+0

'\ u002e' का उपयोग करके ग्रेट पॉइंट ने सफलतापूर्वक ऑब्जेक्ट कुंजी को एन्कोड किया। हालांकि पुनर्प्राप्त करना बोझिल है: डॉक्टर [अनस्कैप ('फ़ील्ड \ u002ename')] मेरे लिए काम नहीं करता है। आपको एक अलग चर में अनस्केप करना है और फिर तदनुसार इसे पुनर्प्राप्त करना है। मैं मोंगो डीबी चालक –

3

तुम भी एक लिख सकते हैं SONManipulator यू प्योंगो लाइब्रेरी गाएं जो मोंगोडब से बाहर और पीछे जाने वाले डेटा को बदल देती है। डाउनसाइड्स हैं; एक प्रदर्शन हिट होता है (प्रभाव आपके उपयोग के मामले पर निर्भर करता है) और जब आप खोज का उपयोग करके खोज करते हैं तो आपको अपनी चाबियाँ बदलनी पड़ती हैं।

from pymongo.son_manipulator import SONManipulator 

class KeyTransform(SONManipulator): 
    """Transforms keys going to database and restores them coming out. 

    This allows keys with dots in them to be used (but does break searching on 
    them unless the find command also uses the transform). 

    Example & test: 
     # To allow `.` (dots) in keys 
     import pymongo 
     client = pymongo.MongoClient("mongodb://localhost") 
     db = client['delete_me'] 
     db.add_son_manipulator(KeyTransform(".", "_dot_")) 
     db['mycol'].remove() 
     db['mycol'].update({'_id': 1}, {'127.0.0.1': 'localhost'}, upsert=True, 
          manipulate=True) 
     print db['mycol'].find().next() 
     print db['mycol'].find({'127_dot_0_dot_0_dot_1': 'localhost'}).next() 

    Note: transformation could be easily extended to be more complex. 
    """ 

    def __init__(self, replace, replacement): 
     self.replace = replace 
     self.replacement = replacement 

    def transform_key(self, key): 
     """Transform key for saving to database.""" 
     return key.replace(self.replace, self.replacement) 

    def revert_key(self, key): 
     """Restore transformed key returning from database.""" 
     return key.replace(self.replacement, self.replace) 

    def transform_incoming(self, son, collection): 
     """Recursively replace all keys that need transforming.""" 
     for (key, value) in son.items(): 
      if self.replace in key: 
       if isinstance(value, dict): 
        son[self.transform_key(key)] = self.transform_incoming(
         son.pop(key), collection) 
       else: 
        son[self.transform_key(key)] = son.pop(key) 
      elif isinstance(value, dict): # recurse into sub-docs 
       son[key] = self.transform_incoming(value, collection) 
     return son 

    def transform_outgoing(self, son, collection): 
     """Recursively restore all transformed keys.""" 
     for (key, value) in son.items(): 
      if self.replacement in key: 
       if isinstance(value, dict): 
        son[self.revert_key(key)] = self.transform_outgoing(
         son.pop(key), collection) 
       else: 
        son[self.revert_key(key)] = son.pop(key) 
      elif isinstance(value, dict): # recurse into sub-docs 
       son[key] = self.transform_outgoing(value, collection) 
     return son 
0
def remove_dots(data): 
    for key in data.keys(): 
     if type(data[key]) is dict: data[key] = remove_dots(data[key]) 
     if '.' in key: 
      data[key.replace('.', '\uff0E')] = data[key] 
      del data[key] 
    return data 

इस पुनरावर्ती विधि \ uff0E के साथ एक dict की चाबी से सभी डॉट पात्रों की जगह:

यहाँ कैसे KeyTransform वर्ग के लिए टिप्पणी में इसका इस्तेमाल करने का एक उदाहरण के साथ कोड है जैसा कि Fisk

+0

आपको इसका उपयोग करना चाहिए: यदि isinstance (date [key] , dict) –

+0

लूप के लिए पहले से ही उपलब्ध कुंजी सूची का उपयोग करता है, मुझे नहीं लगता कि अगर नियंत्रण – tuku

0

द्वारा शुरू किया गया है, प्रारंभ में मैंने सभी को बदलने के लिए एक सरल रिकर्सन का उपयोग किया। " इसके यूनिकोड समकक्ष वाले अक्षर लेकिन यह पता चला कि मूल्यों में भी बिंदुओं को प्रतिस्थापित किया जा रहा था। इसलिए मैंने सोचा कि हमें केवल कुंजियों से बिंदुओं को प्रतिस्थापित करना चाहिए और "अगर इंस्टेंसेंस (इनपुट, dict)" के मामले में तदनुसार परिवर्तन करना चाहिए। मैंने सोचा कि यह जादू करने के लिए पर्याप्त शर्त होनी चाहिए, लेकिन मैं भूल गया था कि ताना मूल्य भी एक ताना या एक सूची हो सकता है और फिर मैंने अंत में कहा कि जांच करें कि यदि एक ताना का मूल्य स्ट्रिंग नहीं था, तो फिर से अंदर जाएं आखिरकार इस समाधान के साथ आने में सक्षम रहा जिसने अंततः चाल की।

def remove_dots(data): 
    if isinstance(data, dict): 
      return {remove_dots(key): value if isinstance(value, str) else remove_dots(value) for key,value in data.iteritems()} 
    elif isinstance(data, list): 
      return [remove_dots(element) for element in data] 
    elif isinstance(data, str): 
      return data.replace('.','\u002e') 
    else:                        
      return data 
+0

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

0

मैं कुंजी मान myString.replace का उपयोग कर प्रतिस्थापित ("।", "\ U2024") JSONObject में डालने से पहले।

0

शब्दकोशों को क्रमबद्ध करने की कोशिश करते समय मैं वास्तव में इस समस्या में आ गया हूं और ऐसे में जहां अपमानजनक बिंदु एक प्रमुख नाम के रूप में दिखाई दे सकता है। संदर्भ दिखाने के लिए संपादित किया गया।

त्वरित और गंदी सी # दृष्टिकोण:

using MongoDB.Bson; 
using Newtonsoft.Json.Linq; 
using System.Text.RegularExpressions; 

public static T Sanitize<T>(T obj) 
{ 
     var str = JObject.FromObject(obj).ToJson(); 
     var parsed = Regex.Replace(str, @"\.(?=[^""]*"":)", "_"); //i.e. replace dot with underscore when found as a json property name { "property.name": "don't.care.what.the.value.is" } 
     return JObject.Parse(parsed).ToObject<T>(); 
} 
संबंधित मुद्दे