Доступ к вложенным полям
Документ 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, callback)
// result passed to callback
"408-555-1212"
С большинством команд, принимающих строку имени поля или синтаксис () выше, вы также можете использовать вложенный синтаксис в стиле JSON:
> r.table('users').get(10001).pluck(
{contact: {phone: "work"}}
).run(conn, callback)
// result passed to callback
{
"contact": {
"phone": {
"work": "408-555-1212"
}
}
}
В этом примере, когда вы пытаетесь получить только одно значение, синтаксис JSON не предлагает существенного преимущества. Но вы можете использовать его для извлечения нескольких значений на одном уровне вложенности. Например, вы можете получить только рабочие и мобильные номера Боба, но не домашний:
> r.table('users').get(10001).pluck(
{contact: {phone: ["work", "cell"]}}
).run(conn, callback)
// result passed to callback
{
"contact": {
"phone": {
"cell": "408-555-1214",
"work": "408-555-1212"
}
}
}
Или, рабочий телефон и Skype Боба:
> r.table('users').get(10001).pluck(
{contact: {phone: 'work', im: 'skype'}}
).run(conn, callback)
// result passed to callback
{
"contact": {
"im": {
"skype": "Bob Smith"
},
"phone": {
"work": "408-555-1212"
}
}
}
И это ещё не всё! Вы можете фильтровать поля объектов внутри списка. Предположим, вам нужны только даты и отправители заметок Боба:
> r.table('users').get(10001).pluck(
{notes: ['date', 'from']}
).run(conn, callback)
// result passed to callback
{
"notes": [
{
"date": Wed Jan 01 2014 00:00:00 GMT+00:00 ,
"from": "John Doe"
},
{
"date": Sun Feb 02 2014 00:00:00 GMT+00:00 ,
"from": "Bob Smith Sr."
}
]
}
Если вы запросите вложенное поле, которого не существует, вы получите пустой объект или массив (это не то же самое, что null значение):
> r.table('users').get(10001).pluck(
{contact: {phone: 'work', im: 'msn'}}
).run(conn, callback)
// result passed to callback
{
"contact": {
"im": { },
"phone": {
"work": "408-555-1212"
}
}
}
Обратите внимание, что это поведение верно и при извлечении данных из списков. Если вы извлекли subject из notes выше, а у Боба было 10 заметок, 3 из которых не содержали subject поля, вы всё равно получите список из 10 объектов: 7 из них будут {subject: <text>}, а 3 — пустыми, т.е., { }.
Ещё один нюанс: синтаксис вложенных полей не гарантирует идентичных схем между документами, которые он возвращает. Возможно, описанный путь соответствует объектам с различными схемами, как показано в этом простом примере.
> r([
{
a: {
b: 1,
c: 2
}
},
{
a: [
{
b: 1,
c: 2
}
]
}
]).pluck({a: {b: true}}).run(conn, callback)
// result passed to callback
[
{
"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/javascript/