$lookup 结果使用来自另一个数组的键排序
Posted
技术标签:
【中文标题】$lookup 结果使用来自另一个数组的键排序【英文标题】:$lookup result sorted using a key from another array 【发布时间】:2018-03-29 00:56:18 【问题描述】:我有以下数据结构:
播放列表集合:
_id:123,
artistId:959789,
title:'playlist1',
tracks:[trackId:123456,createdDate:03.02.2017,
trackId:213556,createdDate:04.02.2017,
trackId:956125,createdDate:05.02.2017]
,
_id:456,
artistId:456456,
title:'playlist2',
tracks:[trackId:956336,createdDate:03.02.2017,
trackId:213556,createdDate:09.02.2017,
trackId:785556,createdDate:011.02.2017]
,
_id:456,
artistId:456456,
title:'playlist3',
tracks:[trackId:636985,createdDate:01.02.2017,
trackId:456585,createdDate:06.02.2017,
trackId:785556,createdDate:09.02.2017]
播放列表曲目数组中的trackId
是曲目集合中曲目的_id
曲目集合:
_id:956336,title:'abc',
_id:785556,title:'cdf',
_id:456585,title:'ghi',
_id:213556,title:'xyz',
_id:636985,title:'lmn'
我所做的是使用tracks
数组中的trackId
聚合$lookup
,我得到了结果。但是playlistTracks
以其他顺序排序,而不是tracks
数组顺序。
$match: artistId: 456
,
$lookup:
from: 'tracks',
localField: 'tracks.trackId',
foreignField: '_id',
as: 'playlistTracks'
,
现在我需要的是获取具有以下结构的特定艺术家的播放列表列表:
playlistTracks
应该按照tracks
数组中createdDate
的顺序排序。
_id:456,
title:'playlist2',
tracks:[trackId:636985,createdDate:01.02.2017,
trackId:456585,createdDate:06.02.2017,
trackId:785556,createdDate:09.02.2017]
playlistTracks:[_id:956336,title:'abc',
_id:213556,title:'xyz',
_id:785556,title:'cdf']
,
_id:456,
title:'playlist2',
tracks:[trackId:636985,createdDate:01.02.2017,
trackId:456585,createdDate:06.02.2017,
trackId:785556,createdDate:09.02.2017]
playlistTracks:[_id:636985,title:'lmn',
_id:456585,title:'ghi',
_id:785556,title:'cdf']
【问题讨论】:
【参考方案1】:所以这些是我添加的文档,用于重现您的用例:
播放列表集合
"_id" : NumberInt(123),
"artistId" : NumberInt(959789),
"title" : "playlist1",
"tracks" : [
"trackId" : NumberInt(123456),
"createdDate" : "03.02.2017"
,
"trackId" : NumberInt(213556),
"createdDate" : "04.02.2017"
,
"trackId" : NumberInt(956125),
"createdDate" : "05.02.2017"
]
"_id" : NumberInt(456),
"artistId" : NumberInt(456456),
"title" : "playlist2",
"tracks" : [
"trackId" : NumberInt(956336),
"createdDate" : "03.02.2017"
,
"trackId" : NumberInt(213556),
"createdDate" : "09.02.2017"
,
"trackId" : NumberInt(785556),
"createdDate" : "11.02.2017"
]
"_id" : NumberInt(457),
"artistId" : NumberInt(456456),
"title" : "playlist3",
"tracks" : [
"trackId" : NumberInt(636985),
"createdDate" : "01.02.2017"
,
"trackId" : NumberInt(456585),
"createdDate" : "06.02.2017"
,
"trackId" : NumberInt(785556),
"createdDate" : "09.02.2017"
]
我将播放列表集合中最后一个重复的 _id 更改为 _id: 457。我不知道您如何拥有两个具有相同 _id
的文档。 _id
字段必须是唯一的。而且我不确定我是否理解正确您想要的结果,因为在您的$match
查询中您写了以下内容:$match: artistId: 456
但在您的数据中没有 artiseId 和 456 em>。
还有这个日期
trackId:785556,createdDate:011.02.2017
从文档 id_456 我更改为
trackId:785556,createdDate:"11.02.2017"
因为日期看起来很奇怪。看起来您的日期字段也是字符串,因为它看起来肯定不像日期字段。无论哪种方式,$sort
都适用于这两种用例。
tracks 集合我在你的例子中留下了。
所以这似乎是你需要的?
db.playlist.aggregate([
$match: _id: $in: [456]
,
$unwind: "$tracks",
$sort: "tracks.createdDate": 1,
$lookup:
from: 'tracks',
localField: 'tracks.trackId',
foreignField: '_id',
as: 'playlistTracks'
,
$group:
_id: "$_id",
artistId: $first: "$artistId",
title: $first: "$title",
tracks: $push: item: "$tracks.trackId", quantity: "$tracks.createdDate" ,
playlistTracks: $push: "$playlistTracks"
])
这会将两个数组排列成相同的顺序。你可以在这里指定$sort: "tracks.createdDate": 1
如果你想升序或降序-1
顺序
因此,在查找字段之前,您可以展开播放列表数组并对其进行排序。 希望这有效
【讨论】:
实际上我希望使用createdDate
对$lookup
的结果进行排序。如果我们这样$unwind
和$sort
,tracks
数组就会被排序。
对不起,我误解了你的问题,我会更新我的答案。
非常感谢您的努力。我尝试过这个。但没有按照我想要的结果工作【参考方案2】:
按照以下步骤进行
1 unwind the tracks array in playlist collection
2 $lookup match with tracks collection
3 add createddate of tracks array to lookup result as a new key
4 sort based on new key
5 group the results for your requirements
【讨论】:
以上是关于$lookup 结果使用来自另一个数组的键排序的主要内容,如果未能解决你的问题,请参考以下文章
编写一个多线程函数实现对数组排序,要求: 1.至少用两个线程 2.数组的元素值可以事先定义好,或者可以从键盘输入(增加一个线程)。 3.用一个线程对数组排序,用另一个线程输出排序结果。 4.保证先排好