Доступ к вложенным полям
Документ ReQL — это JSON-объект: набор пар ключ-значение, где каждое значение может быть одиночным значением, списком значений или другим набором пар ключ-значение. Когда значение поля содержит другие поля, мы называем их вложенными полями.
Рассмотрим таблицу пользователей с контактной информацией и списком заметок для каждого пользователя в таком формате:
{
"id": 10001,
"name": "Bob Smith",
"contact": {
"phone": {
"work": "408-555-1212",
"home": "408-555-1213",
"cell": "408-555-1214"
},
"email": {
"work": "bob@smith.com",
"home": "bobsmith@gmail.com",
"other": "bobbys@moosecall.net"
},
"im": {
"skype": "Bob Smith",
"aim": "bobmoose",
"icq": "nobodyremembersicqnumbers"
}
},
"notes": [
{
"date": r.time(2014,1,1,'Z'),
"from": "John Doe",
"subject": "My name is even more boring than Bob's"
},
{
"date": r.time(2014,2,2,'Z'),
"from": "Bob Smith Sr",
"subject": "Happy Second of February"
}
]
}
Контактная информация вложена, как пути в файловой системе.
contact → phone → work → 408-555-1212
Вы можете получить значение конкретного поля, используя оператор [] последовательно, чтобы «пройтись» по вложенности документа:
> r.table('users').get(10001)['contact']['phone']['work'].run(conn)
'408-555-1212'
В большинстве команд, принимающих строку имени поля или синтаксис [] выше, вы также можете использовать вложенный синтаксис в стиле JSON:
> r.table('users').get(10001).pluck(
{'contact': {'phone': 'work'}}
).run(conn)
{
'contact': {
'phone': {
'work': '408-555-1212'
}
}
}
В этом примере, когда вы пытаетесь получить только одно значение, синтаксис в стиле JSON не предлагает существенного преимущества. Но вы можете использовать его для получения нескольких значений на одном уровне вложенности. Например, вы можете получить только номера телефонов Bob по работе и сотовой связи, но не домашний:
> r.table('users').get(10001).pluck(
{'contact': {'phone': ['work', 'cell']}}
).run(conn)
{
'contact': {
'phone': {
'cell': '408-555-1214',
'work': '408-555-1212'
}
}
}
Или, телефон Bob по работе и Skype-адрес:
> r.table('users').get(10001).pluck(
{'contact': [{'phone': 'work', 'im': 'skype'}]}
).run(conn)
{
'contact': {
'im': {
'skype': 'Bob Smith'
},
'phone': {
'work': '408-555-1212'
}
}
}
И это еще не все! Вы можете фильтровать поля объектов внутри списка. Предположим, вам нужны только даты и отправители заметок Bob:
> r.table('users').get(10001).pluck(
{'notes': ['date', 'from']}
).run(conn)
{
'notes': [
{
'date': '2014-01-01T00:00:00+00:00' ,
'from': 'John Doe'
},
{
'date': '2014-02-02T00:00:00+00:00' ,
'from': 'Bob Smith Sr.'
}
]
}
Если вы запрашиваете вложенное поле, которого не существует, вы получите пустой объект или массив (это не то же самое, что nil значение):
> r.table('users').get(10001).pluck(
{'contact': [{'phone': 'work', 'im': 'msn'}]}
).run(conn)
{
'contact': {
'im': { },
'phone': {
'work': '408-555-1212'
}
}
}
Обратите внимание, что это поведение верно и при получении данных из списков. Если вы извлекли subject из notes выше, и у Bob было 10 заметок, 3 из которых не содержали поля subject, вы все равно получите список из 10 объектов: 7 из них будут {subject: <text>}, а 3 — пустые, то есть { }.
Также, еще один момент: синтаксис вложенных полей не гарантирует идентичных схем между документами, которые он возвращает. Возможно описание пути, соответствующего объектам с различными схемами, как показано в этом простом примере.
> r.expr([
{
'a': {
'b': 1,
'c': 2
}
},
{
'a': [
{
'b': 1,
'c': 2
}
]
}
]).pluck({'a': {'b': true}}).run(conn)
[
{
'a': {
'b': 1
}
},
{
'a': [
{
'b': 1
}
]
}
]
© RethinkDB contributors
Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
https://rethinkdb.com/docs/nested-fields/python/