2017-02-13 73 views
1

嵌套在巢中。 我已經適應我的需要分爲以下幾個餐廳例子:Couchbase N1QL - 嵌套在巢中

所需的輸出:

{ 
    "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 
    } 
} 

實例文檔:

// 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.... } 

我能得到沒有錯誤最接近的是:

SELECT restaurant, mains, drinks 
FROM default restauant USE KEYS "restaurant1" 
NEST default mains ON KEYS restaurant.mainIds 
NEST default drinks ON KEYS restaurant.drinkIds; 

但是:
1.Ob巢穴巢穴丟失
2.退貨的訂單不正確 - 飲料巢先來,而不是最後
(3。由於我還使用SYNC網關 - 它返回所有的「_sync」與每個文檔領域 - 無法弄清楚如何省略此每個DOC)

更新1:適應解
NB:。我應該在上面指出主要不能容納成分ID

基於geraldss' V以下有益輸入,我添加了一個文檔跟蹤每個餐廳鍵,如:我加入這geraldss

{ 
    "id": "restaurant1-JoeBloggs", 
    "dinerId": "JoeBloggs", 
    "ingredientIds": [ "ingredient1", "ingredient2" "ingredient3" ], 
    "mainOrdered": [ "main1" ], // < other potential uses... 
    "drinkOrdered": [ "drink2" ] 
} 

下面爲連接,以將其提供給第一個解決方案查詢,如:

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'下面還第二種解決方案看起來很好 - 不幸的是它不會對我的情況下工作,因爲此查詢要求電源通過成分發現;爲了我的需要,一個主體可以不用任編輯:>他想出了另一種解決方案。請參閱第2

更新2:最終的解決方案

所以,再次與geraldss的幫助下我已經不需要額外的文檔追蹤按鍵的解決方案:

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 - 只有使用Sync Gateway時才需要使用AND meta().id NOT LIKE '_sync:%'行。

只需一個鍵我就可以拉出所有相關的文檔 - 即使它們對於直接的「父」是未知的。
謝謝你geraldss。

回答

0

如果電源包含ingredientIds:

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 main.ingredientIds 
      ) AS ingredients 
     FROM default AS main 
     USE KEYS r.mainIds 
    ) AS mains 
FROM default AS r 
USE KEYS "restaurant1" 
) AS restaurant 
; 

編輯:更新以包括不受任何成分引用電源。

如果電源不包含ingredientIds:

SELECT * 
FROM 
(
SELECT 
    r.*, 
    (
     SELECT 
      drink.* 
    FROM default AS drink 
    USE KEYS r.drinkIds 
    ) AS drinks, 
    (
     SELECT 
      main.*, 
      ARRAY_AGG(ingredient) AS ingredients 
     FROM default AS ingredient 
     JOIN default AS main 
    ON KEYS ingredient.mainIds 
     WHERE "restaurant1" IN main.restaurantIds 
     GROUP BY main 
     UNION ALL 
     SELECT 
      main.* 
     FROM default AS main 
     WHERE "restaurant1" IN main.restaurantIds 
     AND META(main).id NOT IN (
      SELECT RAW mainId 
      FROM default AS ingredient 
      UNNEST mainIds AS mainId 
     ) 
    ) AS mains 
FROM default AS r 
USE KEYS "restaurant1" 
) AS restaurant 
; 
+0

嗨geraldss,非常感謝你爲你的解決方案! 我把你的第一個解決方案,並添加了一個新的索引文件。往上看。 當你嘗試你的第二個解決方案成分回來爲空。也許問題出現在'WHERE「restaurant1」main.restaurantIds'行? 當我用'WHERE ingredient.type =「成分」替換該行時,它開始工作,但我認爲可能需要進一步的條件。 然而,即使這個查詢已經完善,它不適合我的情況,因爲這個查詢需要通過成分找到電源。對於我的情況下,主要可以存在沒有任何成分。 – Giles

+0

您可以將UNION添加到該子查詢中以獲取沒有配料的主電源。 – geraldss

+0

Hi @geraldss。好。根據你的評論,我一直試圖建立一個利用UNION沒有成功的查詢。有什麼機會可以將我指向正確的方向? 如果我可以避免使用額外的文檔來追蹤密鑰,情況會好得多。 – Giles