如何在字段名称中使用点?

时间:2011-12-08 10:13:47

标签: mongodb

如何在字段名称中使用点?

我在示例中看到错误:

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

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

7 个答案:

答案 0 :(得分:46)

您可以将字段名称的点符号替换为等效于\uff0E

的Unicode
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

答案 1 :(得分:4)

Actualy你可以在查询中使用点。请参阅: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"的字段创建文档,其中embeded文档的值包含名为"a"的字段(再次),其值为"b"

答案 2 :(得分:3)

您还可以使用pymongo库编写SONManipulator,该库可以转换进出mongodb的数据。有缺点;性能受到影响(影响取决于您的使用案例),当您使用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

答案 3 :(得分:1)

在将其插入JsonObject之前,我使用myString.replace(“。”,“\ u2024”)替换了键值。

答案 4 :(得分: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键中的所有点字符 正如Fisk

所建议的那样

答案 5 :(得分:0)

最初我使用简单的递归来替换所有“。”与unicode等效的字符,但想到即使值中的点也被替换了。所以我认为我们应该只从键中替换点,并在“if isinstance(input,dict)”的情况下进行相应的更改。 我认为它应该是做魔术的充分条件但我忘了dict值也可以是dict或列表然后我最后添加了检查,如果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

答案 6 :(得分: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>();
}