在 MongoDB 中获取子数组中的上一个和下一个
Get previous and next inside sub array in MongoDB
我有如下数据库。
[
{
"title": "Data 1",
"slug": "data-1",
"sub_docs": [
{
"name": "Sub Doc 1",
"sub_slug": "sub-doc-1",
"urls": [
"https://example.com/path-1",
]
},
{
"name": "Sub Doc 2",
"sub_slug": "sub-doc-2",
"urls": [
"https://example.com/path-2"
]
},
{
"name": "Sub Doc 3",
"sub_slug": "sub-doc-3",
"urls": [
"https://example.com/path-3",
]
}
]
}
]
当我将 data-1 和 sub-doc-2 作为输入时,我想得到以下结果。
{
"title": "Data 1",
"sub_doc_title": "Sub Doc 2",
"urls": [
"https://example.com/path-2"
],
"prev": {
"name": "Sub Doc 1",
"sub_slug": "sub-doc-1"
},
"next": {
"name": "Sub Doc 3",
"sub_slug": "sub-doc-3"
}
}
我是 MongoDB 的新手。
我该如何做这个查询?你有什么想法吗?
这对初学者来说是一个艰难的问题,虽然我仍然认为自己是新手,所以也许有 better/easy 方法。
这是您可以做到的一种方法。
db.collection.aggregate([
{
"$match": {
"slug": "data-1" // given argument
}
},
{
"$set": {
"reduceOut": {
"$reduce": {
"input": "$sub_docs",
"initialValue": {
"sub_doc_title": null,
"urls": [],
"prev": null,
"next": null
},
"in": {
"$cond": [
{
"$eq": [
"$$this.sub_slug",
"sub-doc-2" // given argument
]
},
{
"$mergeObjects": [
"$$value",
{
"sub_doc_title": "$$this.name",
"urls": "$$this.urls"
}
]
},
{
"$cond": [
{ "$eq": [ "$$value.sub_doc_title", null ] },
{
"$mergeObjects": [
"$$value",
{
"prev": {
"name": "$$this.name",
"sub_slug": "$$this.sub_slug"
}
}
]
},
{
"$cond": [
{ "$eq": [ "$$value.next", null ] },
{
"$mergeObjects": [
"$$value",
{
"next": {
"name": "$$this.name",
"sub_slug": "$$this.sub_slug"
}
}
]
},
"$$value"
]
}
]
}
]
}
}
}
}
},
{
"$replaceWith": {
"$mergeObjects": [
{
"title": "$title"
},
"$reduceOut"
]
}
}
])
在 mongoplayground.net 上试用。
感谢 rickhg12hs 的回答。我也找到了这个问题的解决方案。
这是我的答案;
db.collection.aggregate([
{
"$match": {
"slug": "data-1"
}
},
{
"$addFields": {
"sub_doc_index": {
"$indexOfArray": [
"$sub_docs.sub_slug",
"sub-doc-2"
]
}
}
},
{
"$project": {
"title": 1,
"sub_doc_title": {
"$arrayElemAt": [
"$sub_docs.name",
"$sub_doc_index"
]
},
"urls": {
"$arrayElemAt": [
"$sub_docs.urls",
"$sub_doc_index"
]
},
"prev": {
"$cond": {
"if": {
"$eq": [
{
"$subtract": [
"$sub_doc_index",
1
]
},
-1
]
},
"then": {},
"else": {
"name": {
"$arrayElemAt": [
"$sub_docs.name",
{
"$subtract": [
"$sub_doc_index",
1
]
}
]
},
"slug": {
"$arrayElemAt": [
"$sub_docs.sub_slug",
{
"$subtract": [
"$sub_doc_index",
1
]
}
]
}
},
},
},
"next": {
"name": {
"$arrayElemAt": [
"$sub_docs.name",
{
"$add": [
"$sub_doc_index",
1
]
}
]
},
"slug": {
"$arrayElemAt": [
"$sub_docs.sub_slug",
{
"$add": [
"$sub_doc_index",
1
]
}
]
}
}
}
},
])
我有如下数据库。
[
{
"title": "Data 1",
"slug": "data-1",
"sub_docs": [
{
"name": "Sub Doc 1",
"sub_slug": "sub-doc-1",
"urls": [
"https://example.com/path-1",
]
},
{
"name": "Sub Doc 2",
"sub_slug": "sub-doc-2",
"urls": [
"https://example.com/path-2"
]
},
{
"name": "Sub Doc 3",
"sub_slug": "sub-doc-3",
"urls": [
"https://example.com/path-3",
]
}
]
}
]
当我将 data-1 和 sub-doc-2 作为输入时,我想得到以下结果。
{
"title": "Data 1",
"sub_doc_title": "Sub Doc 2",
"urls": [
"https://example.com/path-2"
],
"prev": {
"name": "Sub Doc 1",
"sub_slug": "sub-doc-1"
},
"next": {
"name": "Sub Doc 3",
"sub_slug": "sub-doc-3"
}
}
我是 MongoDB 的新手。 我该如何做这个查询?你有什么想法吗?
这对初学者来说是一个艰难的问题,虽然我仍然认为自己是新手,所以也许有 better/easy 方法。
这是您可以做到的一种方法。
db.collection.aggregate([
{
"$match": {
"slug": "data-1" // given argument
}
},
{
"$set": {
"reduceOut": {
"$reduce": {
"input": "$sub_docs",
"initialValue": {
"sub_doc_title": null,
"urls": [],
"prev": null,
"next": null
},
"in": {
"$cond": [
{
"$eq": [
"$$this.sub_slug",
"sub-doc-2" // given argument
]
},
{
"$mergeObjects": [
"$$value",
{
"sub_doc_title": "$$this.name",
"urls": "$$this.urls"
}
]
},
{
"$cond": [
{ "$eq": [ "$$value.sub_doc_title", null ] },
{
"$mergeObjects": [
"$$value",
{
"prev": {
"name": "$$this.name",
"sub_slug": "$$this.sub_slug"
}
}
]
},
{
"$cond": [
{ "$eq": [ "$$value.next", null ] },
{
"$mergeObjects": [
"$$value",
{
"next": {
"name": "$$this.name",
"sub_slug": "$$this.sub_slug"
}
}
]
},
"$$value"
]
}
]
}
]
}
}
}
}
},
{
"$replaceWith": {
"$mergeObjects": [
{
"title": "$title"
},
"$reduceOut"
]
}
}
])
在 mongoplayground.net 上试用。
感谢 rickhg12hs 的回答。我也找到了这个问题的解决方案。
这是我的答案;
db.collection.aggregate([
{
"$match": {
"slug": "data-1"
}
},
{
"$addFields": {
"sub_doc_index": {
"$indexOfArray": [
"$sub_docs.sub_slug",
"sub-doc-2"
]
}
}
},
{
"$project": {
"title": 1,
"sub_doc_title": {
"$arrayElemAt": [
"$sub_docs.name",
"$sub_doc_index"
]
},
"urls": {
"$arrayElemAt": [
"$sub_docs.urls",
"$sub_doc_index"
]
},
"prev": {
"$cond": {
"if": {
"$eq": [
{
"$subtract": [
"$sub_doc_index",
1
]
},
-1
]
},
"then": {},
"else": {
"name": {
"$arrayElemAt": [
"$sub_docs.name",
{
"$subtract": [
"$sub_doc_index",
1
]
}
]
},
"slug": {
"$arrayElemAt": [
"$sub_docs.sub_slug",
{
"$subtract": [
"$sub_doc_index",
1
]
}
]
}
},
},
},
"next": {
"name": {
"$arrayElemAt": [
"$sub_docs.name",
{
"$add": [
"$sub_doc_index",
1
]
}
]
},
"slug": {
"$arrayElemAt": [
"$sub_docs.sub_slug",
{
"$add": [
"$sub_doc_index",
1
]
}
]
}
}
}
},
])