【发布时间】:2021-05-06 02:42:52
【问题描述】:
我有一个music app,负责根据标签 ID 查找音乐推荐。
涉及两个实体:
-
Song- 歌曲记录包含其名称和该歌曲所属的音乐标签 ID(流派)列表 -
MusicTag- 音乐标签本身,包括 id、name 等。
数据当前存储在 MongoDB 中。
mongo 中的Songs 集合有数百万首歌曲,每首歌曲平均有7 个标签id。
MusicTags 有大约 30K 条记录。
Songs 集合如下所示:
[
{
name: "Metallica - one",
tags: [
"6018703624d8a5e8efa1b76e", // Rock
"601861cc8cef62ba86765017", // Heavy metal
"5fda07ac8db0615c1c503a46" // Hard Rock
]
},
{
name: "Metallica - unforgiven",
tags: [
"6018703624d8a5e8efa1b76e", // Rock
"5fda07ac8db0615c1c503a46", // Metal
]
},
{
name: "Lady Gaga - Bad Romance",
tags: [
"5fc7b9f95e38e17282896b64", // Pop
"5fc729be5e38e17282844eff", // Dance
]
}
]
给定标签"6018703624d8a5e8efa1b76e" (Rock),我想查询Songs 集合并在tags 数组中找到所有带有Rock 标签的歌曲。
在 Mongo 中,这是我正在执行的查询:
db.songs.find({ tags: { $in: [ObjectId("6018703624d8a5e8efa1b76e")] }});
它的性能非常糟糕(在 10 到 40 秒之间,只要集合增长就会变得最差),我尝试以各种方式对 Mongo 进行索引(该表包含更多涉及搜索的数据,例如分数和持续时间,但现在不相关)但我的查询仍然需要太长时间,我无法解释(我阅读了很多官方和非官方的东西)但我觉得以这种嵌套形式保存数据使索引毫无价值,并且每次仍然以某种方式对表进行全面扫描 - 但我无法证明这一点(Mongo“解释”并没有真正向我解释一些事情:))
我正在考虑使用 ElasticSearch,同步所有歌曲数据,并查询它而不是 Mongo,它将作为数据 SSOT 和其他轻量级操作。
但是问题仍然悬而未决,我想确保:在 Elastic 中,我可以以这种形式保存数据(歌曲中的嵌套数组)或者我需要以不同的方式表示它(例如,将其扁平化,以便每条记录都是 song_tag索引等?
谢谢。
【问题讨论】:
-
您好,您可以将解释输出添加到问题中吗?
标签: mongodb elasticsearch query-optimization database-performance