【问题标题】:Change type of field inside mongoDB aggregation and does $lookup utilises index on fields or not?更改 mongoDB 聚合中的字段类型,$lookup 是否使用字段索引?
【发布时间】:2017-04-23 20:57:46
【问题描述】:

我正在使用 $lookup 在 mongodb 中执行连接,现在我在这里遇到了问题。 我有两个集合,第一个包含用户所有书签品牌,第二个包含有关品牌的所有详细信息。现在我正在尝试返回用户添加书签的所有品牌详细信息。

user_bookmarked收藏

{"mobile_no": "8971740148", "brands": ["5829c1df334d40e20e1d1c19", "5829c1df334d40e20e1d1c20", "5829c1df334d40e20e1d1c21"]}

品牌系列

{"_id": ObjectId("5829c1df334d40e20e1d1c19"), "brand_name": "Versace"}
{"_id": ObjectId("5829c1df334d40e20e1d1c20"), "brand_name": "Lee Cooper"}
{"_id": ObjectId("5829c1df334d40e20e1d1c21"), "brand_name": "Levis"}

我的聚合管道代码如下

                { $match: { mobile_no: mobile_no }},
                { $unwind: { path: "$brands", includeArrayIndex: "brandsposition"}},
                { $lookup: {from: "brands",localField: "brands",foreignField: "_id",as: "user_bookmarks"}},

现在我面临的问题是,上面的代码没有返回任何内容,因为我将品牌 ID 作为字符串存储在我的 user_bookmarked 集合中,而不是作为 ObjectId,因此没有返回任何内容。现在谁能告诉我如何更改聚合查询中的字段类型。

我想问的第二件事请告诉我,当使用 $lookup 时,mongodb 是否使用foreign_field 上的索引。因为我使用 explain: true 在聚合管道上方运行,但我没有找到上述查询使用的任何索引,所以输出返回了这个。

db.user_bookmarked.runCommand('aggregate', {pipeline: [{ $match: { mobile_no: mobile_no }},
            { $unwind: { path: "$brands", includeArrayIndex: "brandsposition"}},
            { $lookup: {from: "brands",localField: "brands",foreignField: "_id",as: "user_bookmarks"}}], explain: true})
{
        "waitedMS" : NumberLong(0),
        "stages" : [
                {
                        "$cursor" : {
                                "query" : {
                                        "mobile_no" : "8971740148"
                                },
                                "queryPlanner" : {
                                        "plannerVersion" : 1,
                                        "namespace" : "test.restaurants",
                                        "indexFilterSet" : false,
                                        "parsedQuery" : {
                                                "mobile_no" : {
                                                        "$eq" : "8971740148"
                                                }
                                        },
                                        "winningPlan" : {
                                                "stage" : "COLLSCAN",
                                                "filter" : {
                                                        "mobile_no" : {
                                                                "$eq" : "8971740148"
                                                        }
                                                },
                                                "direction" : "forward"
                                        },
                                        "rejectedPlans" : [ ]
                                }
                        }
                },
                {
                        "$unwind" : {
                                "path" : "$brands",
                                "includeArrayIndex" : "brandsposition"
                        }
                },
                {
                        "$lookup" : {
                                "from" : "brands",
                                "as" : "user_bookmarks",
                                "localField" : "brands",
                                "foreignField" : "_id"
                        }
                }
        ],
        "ok" : 1
}

现在任何人都可以帮助我离开这里我已经搜索了这两个东西,即如何更改聚合内的字段类型以及 $lookup 是否利用索引但没有发现任何有用的东西请帮助我离开这里这将是非常可观的。

【问题讨论】:

  • 为什么不将品牌 ID 存储为对象 ID?这样做的时候你遇到什么问题了吗?
  • 对象 id 的大小与字符串相比要大,而且我已经使用字符串编写了整个代码,所以我只想将 id 保存为字符串而不是 objectids ??

标签: mongodb aggregation-framework mongodb-indexes


【解决方案1】:

您不能将字符串转换为管道中的对象 ID,您必须遍历每个文档并手动转换它,使用类似的东西(无论如何,您不应该存储类型的混合匹配,所以它可能值得更新从长远来看):

how to convert string to numerical values in mongodb

至于 $lookup 是否使用索引,如果您查看此博客中的统计数据,您会发现使用了索引 -

http://guyharrison.squarespace.com/blog/2016/7/4/join-performance-in-mongodb-32-using-lookup.html

【讨论】:

【解决方案2】:

尝试在您的人群之前将您的品牌转换为 ObjectId:

user_bookmarked.brands.map((brand) => return mongoose.Types.ObjectId(brand) )

但您确实应该考虑将它们存储为 refs,您的模型应该类似于:

const user_bookmarked = new mongoose.Schema({
    ...
    brands: [{type: mongoose.Schema.Types.ObjectId, ref: 'Brands'}],
    ...
    })

这样他们从一开始就是 ObjectIds。!

关于第二个问题,我认为这篇文章解释了它:join-performance-in-mongodb-32-using-lookup

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2018-08-06
  • 1970-01-01
  • 2023-03-05
  • 2012-08-14
  • 2023-03-22
  • 1970-01-01
  • 2019-01-27
  • 2019-04-18
相关资源
最近更新 更多