#mongodb #pymongo
#mongodb #pymongo
Вопрос:
У меня есть документы со следующими реквизитами:
{
'published_date': '2020/03/10 07:20:09',
'relationships': [
{'rel_name': 'HAS_REL'},
{'rel_name': 'HAS_NO_REL'},
]
}
Я хочу добавить в каждое поле relationships
, которое имеет rel_name
значение HAS_REL
значения опубликованной даты в качестве свойства dict. Документ станет следующим:
{
'published_date': '2020/03/10 07:20:09',
'relationships': [
{ 'rel_name': 'HAS_REL'
'date': 2020,03,10,07,20,09
},
{'rel_name': 'HAS_NO_REL'},
]
}
Пока мой запрос выглядит примерно так:
TEST_COLLECTION.update_one(
{'_id': ObjectId(document_id)},
{'$set': {'relationships.$[elem].date': {'$dateFromString': '$published_date'}}},
False,
False,
None,
[{'elem.rel_name': 'HAS_RELATIONSHIP'}],
)
Но я получаю сообщение об ошибке:
WriteError: The dollar ($) prefixed field '$dateFromString' in 'parsed.relationships.1.date.$dateFromString' is not valid for storage.
есть идеи?
ОБНОВЛЕНИЕ С первоначальным ответом я обновил запрос следующим образом:
TEST_COLLECTION.update_one(
{'_id': ObjectId(document_id)},
[
{'$set': {
'relationships': {
'$let': {
'vars': {
'date': { '$dateFromString': { 'dateString': '$published_date', format: "%Y/%m/%d %H:%M:%S" } }
},
'in': {
'$map': {
'input': "$relationships",
'in': {
'$cond': {
'if': { '$eq': ["$$this.rel_name", "HAS_REL"] },
'then': { '$mergeObjects': ["$$this", { 'date': "$$date" }] },
'else': "$$this"
}
}
}
}
}
}
}
}
]
)
Однако, похоже, я не получаю правильный документ:
InvalidDocument: документы должны иметь только строковые ключи, ключ был встроен в формат функции
Комментарии:
1. Попробуйте
"format":
2. такая глупая ошибка ^^ слишком много часов кодирования, спасибо @WernfriedDomscheit
Ответ №1:
Взгляните на $dateFromString
Вы должны указать format
поле, если вы не используете формат по умолчанию "%Y-%m-%dT%H:%M:%S.%LZ"
. Хранение значений даты / времени в виде строки обычно является недостатком дизайна.
Итак, это должно быть
{'$dateFromString': { dateString: '$published_date', format: "%Y/%m/%d %H:%M:%S" } }
Обратите внимание, время считается по времени UTC. Установите поле timezone
для указания часового пояса, если требуется.
Имейте в виду, $dateFromString()
это функция агрегирования, поэтому вы должны использовать
TEST_COLLECTION.update_one(
{ '_id': ObjectId(document_id) },
[
{
$set: {
relationships: {
$map: {
input: "$relationships",
in: {
$cond: {
if: { $eq: ["$$this.rel_name", "HAS_REL"] },
then: {
$mergeObjects: [
"$$this",
{
date: {
$dateFromString: {
dateString: '$published_date',
format: "%Y/%m/%d %H:%M:%S"
}
}
}
]
},
else: "$$this"
}
}
}
}
}
}
]
)
или другой стиль:
TEST_COLLECTION.update_one(
{ '_id': ObjectId(document_id) },
[
{
$set: {
relationships: {
$let: {
vars: {
date: { $dateFromString: { dateString: '$published_date', format: "%Y/%m/%d %H:%M:%S" } }
},
in: {
$map: {
input: "$relationships",
in: {
$cond: {
if: { $eq: ["$$this.rel_name", "HAS_REL"] },
then: { $mergeObjects: ["$$this", { date: "$$date" }] },
else: "$$this"
}
}
}
}
}
}
}
}
]
)
Комментарии:
1. Спасибо @Wernfried за ваш ответ. Однако с pymongo это, похоже, не работает, я обновил вопрос