Couchbase N1QL-嵌套中的嵌套
在巢中筑巢。 我已将我的需求调整为以下餐厅示例: 期望输出:Couchbase N1QL-嵌套中的嵌套,couchbase,n1ql,Couchbase,N1ql,在巢中筑巢。 我已将我的需求调整为以下餐厅示例: 期望输出: { "restaurant": { "id": "restaurant1", "name": "Foodie", "mains": [ // < main nested in restaurant { "id": "main1", "title": "Steak and Chips", "in
{
"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
}
}
我能得到的最接近无误的结果是:
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.很明显,嵌套的巢不见了
2.返回的订单不正确-饮料排在第一位,而不是最后一位
3.因为我也在使用同步网关,它会返回每个文档的所有同步字段,所以我不知道如何在每个文档上省略它
更新1:适应的解决方案
注意:我应该在上面指定一个main不能保存ingredentid
基于下面geraldss的v有用输入,我添加了一个跟踪每个餐厅钥匙的文档,例如:
{
"id": "restaurant1-JoeBloggs",
"dinerId": "JoeBloggs",
"ingredientIds": [ "ingredient1", "ingredient2" "ingredient3" ],
"mainOrdered": [ "main1" ], // < other potential uses...
"drinkOrdered": [ "drink2" ]
}
我将其添加到geraldss的第一个解决方案中,作为连接,以使其可用于查询,例如:
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
;
注意-与meta.id不同的“\u sync:%”行只有在使用同步网关时才是必需的
只需一个键,我就可以提取所有相关的文档,即使直接的“家长”不知道它们。
谢谢geraldss。如果电源包含以下元件:
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
;
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
;
编辑:更新以包括未被任何成分引用的主管道
如果电源不包含IngRadientids:
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
;
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
;
嗨,杰拉尔德斯,非常感谢你的解决方案!我采用了您的第一个解决方案,并添加了一个新的索引文档。见上文。在尝试第二种解决方案时,成分返回为空。也许问题出在餐厅1在主餐厅的位置?当我用WHERE-component.type=component替换该行时,它开始工作,尽管我认为可能需要进一步的条件。然而,即使这个查询是完善的,它也不适合我的情况,因为这个查询要求通过成分找到主要成分。在我的例子中,main可以不含任何成分而存在。你可以在子查询中添加一个联合,以拾取不含成分的main。嗨@geraldss。好啊根据你的评论,我一直试图利用UNION建立一个查询,但没有成功。你能给我指出正确的方向吗?如果我能避免用额外的文件来记录钥匙,那就更好了。谢谢你,杰拉尔德斯。我想最不合适的线路是在错误的地方?但是,上面的更新2产生了预期的结果。我在编辑的更新2中也做了一些假设-如果它们不正确或有误导性,请毫不犹豫地编辑我或让我知道。如果没有你的帮助,我是不可能到达那里的!再次感谢。好的,很高兴你有了解决办法。不知道为什么不安对你不起作用。