Nest in einem Nest. Ich habe mein Bedürfnis in das folgende Restaurant Beispiel angepasst:Couchbase N1QL - Nest in einem Nest
gewünschte Ausgabe:
{
"restaurant": {
"id": "restaurant1",
"name": "Foodie",
"mains": [ // < main nested in restaurant
{
"id": "main1",
"title": "Steak and Chips",
"ingredients": [ // < ingredient nested in main (...which is nested in restaurant)
{
"id": "ingredient1",
"title": "steak"
},
{
"id": "ingredient2",
"title": "chips"
}
]
},
{
"id": "main2",
"title": "Fish and Chips",
"ingredients": [
{
"id": "ingredient3",
"title": "fish"
},
{
"id": "ingredient2",
"title": "chips"
}
]
}
]
"drinks": [ you get the idea ] // < drink nested in restaurant
}
}
Beispiel Docs:
// RESTAURANTS
{
"id": "restaurant1",
"type": "restaurant",
"name": "Foodie",
"drinkIds": [ "drink1", "drink2" ],
"mainIds: [ "main1", "main2" ]
},
// MAINS
{
"id": "main1",
"type": "main",
"restaurantIds": [ "restaurant1" ],
"title": "Steak and Chips"
},
{
"id": "main2",
"type": "main",
"restaurantIds": [ "restaurant1" ],
"title": "Fish and Chips"
},
// INGREDIENTS
{
"id": "ingredient1",
"type": "ingredient",
"title": "steak",
"mainIds": [ "main1" ]
},
{
"id": "ingredient2",
"type": "ingredient",
"title": "chips",
"mainIds": [ "main1", "main2" ]
},
{
"id": "ingredient3",
"type": "ingredient",
"title": "fish",
"mainIds": [ "main2" ]
},
// DRINKS
{ you get the idea.... }
Der nächstgelegene ich ohne Fehler bekommen kann, ist:
SELECT restaurant, mains, drinks
FROM default restauant USE KEYS "restaurant1"
NEST default mains ON KEYS restaurant.mainIds
NEST default drinks ON KEYS restaurant.drinkIds;
Aber:
1. Ob das verschachtelte Nest fehlt
2. Die zurückgegebene Bestellung ist falsch - die Getränke Nest kommt zuerst anstelle der letzten
(3. Da ich Sync-Gateway auch mit - es gibt alle „_sync“ Felder mit jedem doc - kann nicht herausfinden, wie diese auf jedem doc wegzulassen)
UPDATE 1: angepasste Lösung
NB:. Ich sollte oben angegeben haben, dass ein Haupt nicht ingentantIds halten kann.
Basierend auf geraldss' v hilfreich Eingang unten, habe ich eine doc, die Schlüssel pro Restaurant, zB Tracks:
{
"id": "restaurant1-JoeBloggs",
"dinerId": "JoeBloggs",
"ingredientIds": [ "ingredient1", "ingredient2" "ingredient3" ],
"mainOrdered": [ "main1" ], // < other potential uses...
"drinkOrdered": [ "drink2" ]
}
ich diese hinzugefügt geraldss' auf die erste Lösung unten als JOIN, um es verfügbar Abfrage, zB:
SELECT *
FROM
(
SELECT
r.*,
(
SELECT
drink.*
FROM default AS drink
USE KEYS r.drinkIds
) AS drinks,
(
SELECT
main.*,
(
SELECT
ingredient.*
FROM default AS ingredient
USE KEYS keyIndex.ingredientIds // < keyIndex
WHERE ingredient.mainId=main.id
) AS ingredients
FROM default AS main
USE KEYS r.mainIds
) AS mains
FROM default AS r
USE KEYS "restaurant1"
JOIN default AS keyIndex ON KEYS "restaurant1-JoeBloggs" // < keyIndex JOINed
) AS restaurant
;
geraldss' zweite Lösung unten auch sieht gut aus - leider wird es nicht für meinen Fall arbeiten, wie diese Abfrage erfordert, dass Netz über Zutaten zu finden ist; für meine Bedürfnisse kann ein Haupt ohne Bestandteile bestehen. EDIT:> er kam mit einer anderen Lösung. Siehe 2.
UPDATE 2: ENDLöSUNG
Also, noch einmal, mit geraldss' Hilfe, die ich eine Lösung, die keine zusätzlichen doc erfordert Schlüssel zu verfolgen:
SELECT *
FROM
(
SELECT
restaurant.id, restaurant.name,
(
SELECT
drink.id, drink.title
FROM default AS drink
USE KEYS restaurant.drinkIds
)
AS drinks,
(
SELECT
main.id, main.title,
ARRAY_AGG({"title":ingredient.title, "id":ingredient.id}) AS ingredients
FROM default AS ingredient
JOIN default AS main
ON KEYS ingredient.mainIds
WHERE main.restaurantId="restaurant1"
AND meta().id NOT LIKE '_sync:%' // < necessary only if using Sync Gateway
GROUP BY main
UNION ALL
SELECT
mainWithNoIngredients.id, mainWithNoIngredients.title
FROM default AS mainWithNoIngredients
UNNEST mainWithNoIngredients AS foo // < since this is being flattened the AS name is irrelevant
WHERE mainWithNoIngredients.restaurantId="restaurant1"
AND mainWithNoIngredients.type="main"
AND meta().id NOT LIKE '_sync:%' // < necessary only if using Sync Gateway
AND META(mainWithNoIngredients).id NOT IN
(
SELECT RAW mainId
FROM default AS ingredient
)
)
AS mains
FROM default AS restaurant
USE KEYS "restaurant1"
)
AS restaurant
;
NB - Die Zeilen AND meta().id NOT LIKE '_sync:%'
sind nur erforderlich, wenn Sync Gateway verwendet wird.
Mit nur einem Schlüssel kann ich alle zugehörigen Dokumente ziehen - auch wenn sie dem unmittelbaren "Eltern" unbekannt sind.
Danke Geraldss.
Hallo geraldss, Vielen Dank für Ihre Lösungen! Ich nahm Ihre erste Lösung und fügte ein neues Indizierungsdokument hinzu. Siehe oben. Beim Versuch, Ihre zweite Lösung Zutaten kamen als null zurück. Vielleicht liegt das Problem in der Zeile "WHERE" restaurant1 "IN main.restaurantIds"? Wenn ich diese Zeile durch 'WHERE ingredient.type =" ingredient "ersetze, fängt es an zu arbeiten, obwohl ich denke, dass weitere Bedingungen erforderlich sein könnten. Allerdings, auch wenn diese Abfrage perfektioniert wurde, ist es nicht für meinen Fall geeignet, da diese Abfrage erfordert, dass Hauptleitungen über Bestandteile gefunden werden. Für mich kann ein Main ohne Zutaten existieren. – Giles
Sie können eine UNION zu dieser Unterabfrage hinzufügen, um Hauptleitungen aufzunehmen, die keine Zutaten enthalten. – geraldss
Hallo @geraldss. OK. Basierend auf Ihrem Kommentar habe ich versucht, eine Abfrage mit UNION ohne Erfolg zu erstellen. Kannst du mich in die richtige Richtung lenken? Es wäre viel besser, wenn ich vermeiden könnte, ein zusätzliches Dokument zu verwenden, nur um die Schlüssel zu verfolgen. – Giles