Предложение WHERE для массива в Azure DocumentDb

В документе Azure Documentdb, подобном этому

{
"id": "WakefieldFamily",
"parents": [
    { "familyName": "Wakefield", "givenName": "Robin" },
    { "familyName": "Miller", "givenName": "Ben" }
],
"children": [
    {
        "familyName": "Merriam", 
        "givenName": "Jesse", 
        "gender": "female", 
        "grade": 1,
        "pets": [
            { "givenName": "Goofy" },
            { "givenName": "Shadow" }
        ]
    },
    { 
      "familyName": "Miller", 
      "givenName": "Lisa", 
      "gender": "female", 
      "grade": 8 
    }
],
  "address": { "state": "NY", "county": "Manhattan", "city": "NY" },
  "isRegistered": false
};

Как мне запросить, чтобы получить детей, чьих питомцев зовут "Гуфи"?

Похоже, следующий синтаксис недействителен

Select * from root r
WHERE r.children.pets.givenName="Goofy"

Вместо этого мне нужно сделать

Select * from root r
WHERE r.children[0].pets[0].givenName="Goofy"

который на самом деле не выполняет поиск в массиве.

Любые предложения о том, как мне обрабатывать подобные запросы?


person Avinash Gadiraju    schedule 09.12.2014    source источник


Ответы (2)


Вы должны воспользоваться предложением DocumentDB JOIN, которое работает немного иначе, чем JOIN в RDBM (поскольку DocumentDB имеет дело с денормализованной моделью данных для документов без схемы).

Проще говоря, вы можете думать о DocumentDB JOIN как о самосоединениях, которые можно использовать для формирования перекрестных продуктов между вложенными объектами JSON.

В контексте опроса детей, чьих питомцев зовут "Гуфи", вы можете попробовать:

SELECT 
    f.id AS familyName,
    c AS child,
    p.givenName AS petName 
FROM Families f 
JOIN c IN f.children 
JOIN p IN c.pets
WHERE p.givenName = "Goofy"

Что возвращает:

[{
    familyName: WakefieldFamily,
    child: {
        familyName: Merriam,
        givenName: Jesse,
        gender: female,
        grade: 1,
        pets: [{
            givenName: Goofy
        }, {
            givenName: Shadow
        }]
    },
    petName: Goofy
}]

Ссылка: http://azure.microsoft.com/en-us/documentation/articles/documentdb-sql-query/

Изменить:

Вы также можете использовать функцию ARRAY_CONTAINS, которая выглядит примерно так:

SELECT food.id, food.description, food.tags
FROM food
WHERE food.id = "09052" or ARRAY_CONTAINS(food.tags.name, "blueberries")
person Andrew Liu    schedule 09.12.2014
comment
Спасибо за ответ .. Я узнал, что мне нужно присоединяться только к массиву, но не ко всем узлам. Еще раз спасибо, спасла мне день. - person Avinash Gadiraju; 10.12.2014
comment
как мне это сделать с помощью Linq? - person Nathan Tregillus; 07.03.2017
comment
select f. * по какой-то причине недействителен? Мне нужно указать все атрибуты корневого элемента вручную? - person Tony Gutierrez; 18.04.2017
comment
Вы можете просто использовать SELECT f, чтобы получить все атрибуты в корневом документе - person Andrew Liu; 20.04.2017
comment
Я пытаюсь выполнить этот оператор [выберите * из c, где array_contains (c.Parents.FirstName, Ben)] в обозревателе запросов azure docdb, используя образцы записей и получаю пустой результат, но [выберите * из c, где c.LastName = Wakefield]. Неожиданно работает более сложный оператор соединения [выберите f.LastName как familyName, p как родительский элемент из Familes, f соедините p в f.Parents, где p.FirstName = Ben]. Любые идеи относительно того, что я упускаю из виду, чтобы получить более простой подход array_contains, или куда я должен пойти, чтобы понять, почему это не работает, используя то, что я ожидал, данные выше q / a подробности? - person myusrn; 03.10.2017
comment
И аналогично этот простой оператор [select * from Familes f order by f._ts desc] работает, но этот оператор [select * from Families f order by f.LastName desc] возвращает пустой набор, который не имеет смысла. В справочной документации, которую я читал, говорится, что все в json-документе проиндексировано, и я даже попытался воссоздать коллекцию с настраиваемым RangeIndex, который имеет конкретную запись IndexingPolicy.IncludedPaths для / LastName /? и это не повлияло на результат. - person myusrn; 03.10.2017
comment
@AndrewLiu Не могли бы вы дать совет по моему недавнему вопросу? Спасибо - person Lynn; 13.08.2020

Я думаю, что функция ARRAY_CONTAINS изменилась с тех пор, как на нее был дан ответ в 2014 году. Чтобы она работала, мне пришлось использовать следующее.

SELECT * FROM c
WHERE ARRAY_CONTAINS(c.Samples, {"TimeBasis":"5MIN_AV", "Value":"5.105"},true)

Образцы - это мой массив JSON, который содержит объекты со многими свойствами, включая два указанных выше.

person Nicholas    schedule 18.09.2018
comment
Это помогло. Но даже это у меня не работает, как написано. Мне пришлось заключить TimeBasis в кавычки (), как вы это сделали для Value. - person Krumelur; 01.08.2020
comment
@Krumelur спасибо за внимание, просто опечатка в моем ответе. :-) - person Nicholas; 22.10.2020