2011-12-08 24 views
24

dot in field nameの使い方は?dot in field nameの使い方は?

私は例のエラーを参照してください。あなたは、クエリのドットを使用することができActualy

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

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

何 '' "\の.A" は? –

+0

'' a \ .a "'は何の違いもありません。文字列はまだ '' a.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"という名前のフィールドを含む埋め込みドキュメントの値()のドキュメントが作成されます。

44

あなたは\uff0E

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

のUnicodeの同等に自分のフィールド名のドットシンボルを置き換えることができますもっと見る:

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

私は、期間のUnicodeは "\ u002e"だと思っていました。 – William

+3

@ウィリアムあなたが示唆する純粋なユニコードを使用すると、それはとにかくASCII期間に変わります。それはそれを指定するファンシーな方法です。 \ uFFOEは "FULLWIDTH FULL STOP"文字で、非ASCII文字は無視されます。 \ "1ドットリーダー"の文字は、通常の期間と同じようにスペースの中央に配置されているので、見た目がよくなるかもしれません。 [Appleの製品では、実際の期間と同じように、2024文字がはるかによく見えることを確認しました。] –

+0

'\ u002e'を使用した素晴らしい点は、オブジェクトキーを正常にエンコードしました。取得は面倒です:doc [unescape( 'field \ u002ename'])は私のためには機能しません。別の変数でunescapeを実行し、それに応じてそれを取得する必要があります。私はむしろストリンギングし、トラブルはMongo Db Driverと対戦しています。 –

3

ます。また、書くことができますSONManipulator u mongodbに出入りするデータを変換するpymongoライブラリを歌います。欠点があります。パフォーマンスのヒットがあり(影響はユースケースによって異なります)、findを使用して検索を行うときにキーを変換する必要があります。ここで

は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 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 と辞書のキーからすべてのドット文字を置き換えますFisk

+0

ifinstance(date [key] 、dict) –

+0

forループは既に使用可能なキーリストを使用していますが、私は制御を別のものにする必要はないと思っています – tuku

0

最初はすべての "。"を置き換えるために単純な再帰を使用しました。文字はそのユニコードで同等ですが、値のドットさえも置換されていることが分かりました。そこで私は、キーからのドットだけを置き換え、if isinstance(input、dict)の場合に応じて変更を加えなければならないと考えました。 私はそれが魔法を行うのに十分な条件であるべきだと思っていましたが、私はdict値がdictまたはlistでもあるかもしれないことを忘れていました。最終的にはこのトリックをしたこの解決策を思いつくことができました。

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

あなたの変数がデータと呼ばれるので、 'input'を 'data'また、 'input'を使用すると、input()の組み込み関数が貧弱な形でシャドーされます。キー内のオブジェクト選択にはピリオドが必要なため、値を変更する必要があります。 –

0

私はキー値をmyString.replace( "。"、 "\ u2024")で置き換えてからJsonObjectに挿入しました。

0

ディクショナリをシリアル化しようとしているときなど、問題のあるドットがキー名として表示される場合があります。 編集して参照を表示します。

迅速かつ汚いC#のアプローチ:

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>(); 
}