Mongodb:以正确的顺序使用 $graphLookup、$reduce 和 $concat 构建类别 url
Mongodb: Build category url with $graphLookup, $reduce & $concat in the right order
我尝试存档的是按正确的顺序获取 URL 作为文档的父项。
我生成了这个查询:
输入
use('testdb');
db.categories.drop();
db.categories.insertMany([
{ '_id' : 'shoes', 'name' : 'Shoes', 'path' : 'shoes', 'parent': null},
{ '_id' : 'sportshoes', 'name' : 'Sport-Shoes', 'path' : 'sportshoes', 'parent': 'shoes'},
{ '_id' : 'sportshoes-black', 'name' : 'Sportshoes Black', 'path' : 'sportshoes-black', 'parent': 'sportshoes'},
{ '_id' : 'sportshoes-black-m', 'name' : 'Sportshoes Black M', 'path' : 'sportshoes-black-m', 'parent': 'sportshoes-black'},
{ '_id' : 'sportshoes-black-w', 'name' : 'Sportshoes Black W', 'path' : 'sportshoes-black-w', 'parent': 'sportshoes-black'},
]);
db.categories.aggregate( [
{$match: { _id: 'sportshoes-black-m' } },
{
$graphLookup: {
from: "categories",
startWith: "$parent",
connectFromField: "parent",
connectToField: "_id",
as: "url"
}
},
{
$project: {
"name": 1,
"url" : {
$reduce: {
input: "$url.path",
initialValue: "",
in: {
'$concat': [
'$$value',
{'$cond': [{'$eq': ['$$value', '']}, '', '/']}, '$$this']
}
}
}
}
}
]
)
输出
[
{
_id: 'sportshoes-black-m',
name: 'Sportshoes Black M',
url: 'shoes/sportshoes/sportshoes-black'
}
]
对于这个例子,这是正确的顺序,但是当我尝试获取 sportshoes-black-w
时,我得到的顺序是错误的:
输出
[
{
_id: 'sportshoes-black-w',
name: 'Sportshoes Black W',
url: 'sportshoes-black/sportshoes/shoes'
}
]
你所要做的就是之前对 url 进行排序,如果你有机会使用 Mongo v4.4,引入了 $function
,此运算符允许应用自定义 javascript 函数来实现 MongoDB 查询语言不支持的行为,例如像这样对数组进行排序:
db.categories.aggregate([
{$match: {_id: 'sportshoes-black-m'}},
{
$graphLookup: {
from: "categories",
startWith: "$parent",
connectFromField: "parent",
connectToField: "_id",
as: "url"
}
},
{
$addFields: {
"url": {
$function: {
body: function (urls) {
urls.sort((a, b) => a.path > b.path);
return urls;
},
args: ["$url"],
lang: "js"
}
}
}
},
{
$project: {
"name": 1,
"url": {
$reduce: {
input: "$url.path",
initialValue: "",
in: {
'$concat': [
'$$value',
{'$cond': [{'$eq': ['$$value', '']}, '', '/']}, '$$this']
}
}
}
}
}
])
遗憾的是,以前的 Mongo 版本不存在这样的功能,您必须 $unwind
、$sort
然后 $group
才能恢复您想要的结构,出于明显的原因,这是非常昂贵的,所以在那种情况下,我建议您只在代码 post 聚合中进行排序。
我尝试存档的是按正确的顺序获取 URL 作为文档的父项。
我生成了这个查询:
输入
use('testdb');
db.categories.drop();
db.categories.insertMany([
{ '_id' : 'shoes', 'name' : 'Shoes', 'path' : 'shoes', 'parent': null},
{ '_id' : 'sportshoes', 'name' : 'Sport-Shoes', 'path' : 'sportshoes', 'parent': 'shoes'},
{ '_id' : 'sportshoes-black', 'name' : 'Sportshoes Black', 'path' : 'sportshoes-black', 'parent': 'sportshoes'},
{ '_id' : 'sportshoes-black-m', 'name' : 'Sportshoes Black M', 'path' : 'sportshoes-black-m', 'parent': 'sportshoes-black'},
{ '_id' : 'sportshoes-black-w', 'name' : 'Sportshoes Black W', 'path' : 'sportshoes-black-w', 'parent': 'sportshoes-black'},
]);
db.categories.aggregate( [
{$match: { _id: 'sportshoes-black-m' } },
{
$graphLookup: {
from: "categories",
startWith: "$parent",
connectFromField: "parent",
connectToField: "_id",
as: "url"
}
},
{
$project: {
"name": 1,
"url" : {
$reduce: {
input: "$url.path",
initialValue: "",
in: {
'$concat': [
'$$value',
{'$cond': [{'$eq': ['$$value', '']}, '', '/']}, '$$this']
}
}
}
}
}
]
)
输出
[
{
_id: 'sportshoes-black-m',
name: 'Sportshoes Black M',
url: 'shoes/sportshoes/sportshoes-black'
}
]
对于这个例子,这是正确的顺序,但是当我尝试获取 sportshoes-black-w
时,我得到的顺序是错误的:
输出
[
{
_id: 'sportshoes-black-w',
name: 'Sportshoes Black W',
url: 'sportshoes-black/sportshoes/shoes'
}
]
你所要做的就是之前对 url 进行排序,如果你有机会使用 Mongo v4.4,引入了 $function
,此运算符允许应用自定义 javascript 函数来实现 MongoDB 查询语言不支持的行为,例如像这样对数组进行排序:
db.categories.aggregate([
{$match: {_id: 'sportshoes-black-m'}},
{
$graphLookup: {
from: "categories",
startWith: "$parent",
connectFromField: "parent",
connectToField: "_id",
as: "url"
}
},
{
$addFields: {
"url": {
$function: {
body: function (urls) {
urls.sort((a, b) => a.path > b.path);
return urls;
},
args: ["$url"],
lang: "js"
}
}
}
},
{
$project: {
"name": 1,
"url": {
$reduce: {
input: "$url.path",
initialValue: "",
in: {
'$concat': [
'$$value',
{'$cond': [{'$eq': ['$$value', '']}, '', '/']}, '$$this']
}
}
}
}
}
])
遗憾的是,以前的 Mongo 版本不存在这样的功能,您必须 $unwind
、$sort
然后 $group
才能恢复您想要的结构,出于明显的原因,这是非常昂贵的,所以在那种情况下,我建议您只在代码 post 聚合中进行排序。