Come usare il punto nel nome del campo?

Come usare il punto nel nome del campo?

Vedo errore nell’esempio:

db.test2.insert({ "aa" : "b" }) can't have . in field names [aa] 

Puoi sostituire i simboli punto del nome del tuo campo in equivalente Unicode di \uff0E

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

Vedi altro:

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

In realtà è ansible utilizzare i punti nelle query. Vedi: http://www.mongodb.org/display/DOCS/Dot+Notation+%28Reaching+into+Objects%29

A causa di questo speciale simbolo del punto non è ansible utilizzarlo nei nomi dei campi. Come non è ansible utilizzare il simbolo del punto negli identificatori nella maggior parte dei linguaggi di programmazione.

Puoi scrivere query db.test2.find({ "aa" : "b" }) ma se vuoi essere in grado di scrivere una query di questo tipo devi inserire il tuo object in questo modo: db.test2.insert({"a": {"a": "b"}}) . Questo creerà un documento con il campo "a" con il valore del documento embeded contenente il campo "a" (di nuovo) con il valore "b" .

Puoi anche scrivere un SONManipulator usando la libreria pymongo che trasforma i dati in entrata e in uscita da mongodb. Ci sono aspetti negativi; c’è un calo di prestazioni (l’impatto dipende dal tuo caso d’uso) e devi trasformare le tue chiavi quando fai ricerche usando find.

Ecco il codice con un esempio di come utilizzarlo nel commento per la class KeyTransform:

 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 transformsd 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 transformsd 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 
 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 

questo metodo ricorsivo sostituisce tutti i caratteri punto dalle chiavi di un dict con \ uff0E come suggerito da Fisk

Ho sostituito il valore della chiave usando myString.replace (“.”, “\ U2024”) prima di inserirlo in JsonObject.

Inizialmente ho usato una semplice ricorsione per sostituire tutto “.” personaggi con il suo equivalente in Unicode ma ha capito che anche i punti nei valori venivano rimpiazzati. Quindi ho pensato che dovremmo sostituire i punti solo con le chiavi e apportare le modifiche di conseguenza nel caso “if isinstance (input, dict)”. Ho pensato che dovrebbe essere una condizione sufficiente per fare la magia ma ho dimenticato che il valore di dict può anche essere un dittato o un elenco e poi ho finalmente aggiunto che controllare se il valore di un dict non fosse una stringa, andare all’interno in modo ricorsivo ed infine in grado di venire con questa soluzione che alla fine ha fatto il trucco.

 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 

Ho davvero incontrato questo problema quando provo a serializzare i dizionari e ad esempio dove il punto incriminato può apparire come un nome di chiave. Modificato per mostrare i riferimenti.

L’approccio C # veloce e sporco:

 using MongoDB.Bson; using Newtonsoft.Json.Linq; using System.Text.RegularExpressions; public static T Sanitize(T obj) { var str = JObject.FromObject(obj).ToJson(); var parsed = Regex.Replace(str, @"\.(?=[^""]*"":)", "_"); //ie 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(); }