Доступ к вложенным полям
Документ ReQL — это JSON-объект: набор пар ключ-значение, где каждое значение может быть отдельным значением, списком значений или другим набором пар ключ-значение. Когда значение поля содержит другие поля, мы называем их вложенными полями.
Рассмотрим таблицу пользователей с контактной информацией и списком заметок для каждого пользователя в таком формате. (Мы покажем это в 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
Вы можете получить значение определенного поля, используя g() (getField) последовательно, чтобы «погрузиться» в структуру вложенности документа:
r.table("users").get(10001).g("contact").g("phone").g("work").run(conn);
// result: "408-555-1212"
Большинство команд также позволяют использовать hashMap для приближения вложенной синтаксиса JSON:
r.table("users").get(10001).pluck(
r.hashMap("contact", r.hashMap("phone", "work"))
).run(conn);
Результат:
{
"contact": {
"phone": {
"work": "408-555-1212"
}
}
}
В этом примере, когда вы пытаетесь получить только одно значение, hashMap стиль не предоставляет большого преимущества. Но вы можете использовать его для извлечения нескольких значений на одном уровне вложенности. Например, вы можете получить только номера телефонов работы и сотовой связи Боба, но не домашний:
r.table("users").get(10001).pluck(
r.hashMap("contact", r.hashMap("phone", r.array("work", "cell")))
).run(conn);
Результат:
{
"contact": {
"phone": {
"cell": "408-555-1214",
"work": "408-555-1212"
}
}
}
Или, номер телефона работы и Skype Боба:
r.table("users").get(10001).pluck(
r.hashMap("contact", r.array(
r.hashMap("phone", "work").with("im", "skype")
))
).run(conn);
{
"contact": {
"im": {
"skype": "Bob Smith"
},
"phone": {
"work": "408-555-1212"
}
}
}
И это еще не все! Вы можете фильтровать поля объектов внутри списка. Предположим, вы хотели только даты и отправителей заметок Боба:
r.table("users").get(10001).pluck(
r.hashMap("notes", r.array("date", "from"))
).run(conn);
{
"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(
r.hashMap("contact", r.array(
r.hashMap("phone", "work").with("im", "msn")
))
).run(conn);
{
"contact": {
"im": { },
"phone": {
"work": "408-555-1212"
}
}
}
Обратите внимание, что это поведение также сохраняется при извлечении данных из списков. Если вы извлекли subject из notes выше, и у Боба было 10 заметок, 3 из которых не содержали subject поле, вы по-прежнему получите список из 10 объектов: 7 из них будут {subject: <text>} и 3 из них будут пустыми, то есть { }.
Также есть еще одно замечание: синтаксис вложенных полей не гарантирует одинаковых схем между документами, которые он возвращает. Возможно, описание пути соответствует объектам с различными схемами, как показано в этом простом примере.
r.expr(
r.array(
r.hashMap("a",
r.hashMap("b", 1)
.with("c", 2)
),
r.hashMap("a",
r.array(
r.hashMap("b", 1)
.with("c", 2)
)
)
)
).pluck(r.hashMap("a", r.hashMap("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/java/