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

Pymongo или Mongodb обрабатывает два равных словаря python как разные объекты. Могу ли я заставить их лечиться одинаково?

Пожалуйста, просмотрите следующие строки кода и результаты:

import pymongo

d1 = {'p': 0.5, 'theta': 100, 'sigma': 20}
d2 = {'theta': 100, 'sigma': 20, 'p': 0.5}

I get the following results:

d1 == d2 // Returns True

collectn.find({'goods.H': d1}).count() // Returns 33

collectn.find({'goods.H': d2}).count() // Returns 2

где collectn - объект коллекций Mongodb.

Есть ли способ или способ запроса, чтобы получить те же результаты для вышеупомянутых двух запросов?

Они по существу используют один и тот же словарь (в смысл d1 == d2 составляет True). Я пытаюсь сделать следующее: перед тем, как вставить запись в базу данных, я проверяю, есть ли уже существует запись с добавленной точной комбинацией значений. Если да, то я не хочу делать новую запись. Но из-за вышеизложенного показанного поведения становится возможным получить, что запись не существует даже когда это происходит, и дублирующая запись добавляется в базу данных (конечно, с разными _id но все остальные значения одинаковы, и я бы предпочел не иметь этого).

Заранее благодарим вас за помощь.

4b9b3361

Ответ 1

Проблема, с которой вы столкнулись, объясняется в документации mongodb здесь. Это также связано с тем, что словари Python неупорядочены, а объекты MongoDB упорядочены объектами BSON.

Соответствующая цитата:

Соотношения равенства в поддокументах выбирают документы, если поддокумент соответствует точно указанному вложенному документу, включая порядок полей.

Я думаю, вам может быть лучше, если вы обрабатываете все три свойства как подпрограммы основного объекта, а не один набор свойств, который является подобъектом. Таким образом, упорядочение подобъекта не принудительно вводится в запрос интерпретатором python.

Например...

d1 = {'goods.H.p': 0.5, 'goods.H.theta': 100, 'goods.H.sigma': 20}
d2 = {'goods.H.theta': 100, 'goods.H.sigma': 20, 'goods.H.p': 0.5}

collectn.find(d1).count()
collectn.find(d2).count()

... может давать более согласованные результаты.

Наконец, способ сделать это меняет меньше кода:

collectn.find({'goods.H.' + k:v for k,v in d1.items()})
collectn.find({'goods.H.' + k:v for k,v in d2.items()})

Ответ 2

Я могу только подумать о двух вещах:

  • Создайте свой запрос следующим образом: collectn.find({'goods.H.p':0.5, 'goods.H.theta':100, 'goods.H.sigma': 20}). count(). Это найдет правильное количество документов...

  • Реструктурируйте свои данные → если вы посмотрите на MongoDB: порядок индексов и порядок запросов должны совпадать? вы можете индексировать на p, sigma, theta, так что когда в запросе любой порядок условий предоставит правильный результат. В моих кратких тестах (я не эксперт) я не смог индексировать таким образом, который производит тот же эффект с вашей текущей структурой.

Ответ 3

Я думаю, что ваша проблема упоминается в mongodb doc:

Поле должно точно соответствовать субдоку, включая порядок....

посмотрите здесь. Пример с суб-документом.

Поля в суб-документе должны быть в том же порядке, что и в запросе, который нужно сопоставить.

Ответ 4

Я думаю, что вы ищете $где оператор.

Это работает в Node:

var myCursor = coll.find({$where: function () {return obj.goods.H == d1}});
myCursor.count(function (err, myCount) {console.log(myCount)});

В Python я считаю, что вам нужно передать объект кода BSON.

Документация предупреждает, что оператор $where следует использовать как последнее средство, поскольку он имеет ограничение производительности и не может использовать индексы.

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