Подтвердить что ты не робот

Как использовать точку в имени поля?

Как использовать точку в имени поля?

Я вижу ошибку в примере:

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

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

Ответ 2

Фактически вы можете использовать точки в запросах. См.: 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".

Ответ 3

Вы также можете написать SONManipulator, используя библиотеку pymongo, которая преобразует данные, идущие в и обратно из 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

Ответ 4

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

этот рекурсивный метод заменяет все точечные символы из ключей dict с помощью \uff0E как предложено Fisk

Ответ 5

Сначала я использовал простую рекурсию, чтобы заменить все "." символы с его уникодным эквивалентом, но выяснили, что даже точки в значениях заменяются. Поэтому я подумал, что мы должны заменить точки только с помощью клавиш и соответственно внести изменения в случае "если isinstance (input, 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

Я заменил значение ключа, используя myString.replace( ".", "\ u2024" ), прежде чем вставлять его в JsonObject.

Ответ 7

Я действительно столкнулся с этой проблемой при попытке сериализации словарей и таких, где оскорбительная точка может отображаться как ключевое имя. Отредактировано, чтобы показать ссылки.

Быстрый и грязный подход С#:

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