【问题标题】:MongoDB: Can't canonicalize query: BadValue Projection cannot have a mix of inclusion and exclusionMongoDB:无法规范化查询:BadValue Projection 不能混合包含和排除
【发布时间】:2014-09-16 22:38:02
【问题描述】:

我是使用 CakePHP 的 MongoDB 新手。

当我编写以下查询时,它会执行得很好。

db.testData.find()
{
    "_id" : ObjectId("53d1f79db8173a625961ff3d"),
    "name" : "sadikhasan",
    "created" : ISODate("2014-07-25T06:22:21.701Z")
}

当我运行以下查询以仅获取 name 时,它返回错误:

db.testData.find({},{name:1, created:0})
error: {
    "$err" : "Can't canonicalize query: BadValue Projection cannot 
              have a mix of inclusion and exclusion.",
    "code" : 17287
}

当我运行以下查询以仅获取 name_id:0 时,它执行得很好:

db.testData.find({},{name:1, _id:0})
{ "name" : "sadikhasan" }

我的问题是,为什么我在投影列表中写created:0 时会出错。提前感谢您的帮助。

【问题讨论】:

    标签: mongodb mongodb-query


    【解决方案1】:

    您不能混合包含和排除,唯一的例外是_id 字段。

    例如,如果你有这个:

    {
       "_id": ObjectId("53d1fd30bdcf7d52c0d217de"),
       "name": "bill",
       "birthdate": ISODate("2014-07-80T00:00:00.000Z"),
       "created": ISODate("2014-07-25T06:44:38.641Z")
    }
    

    如果您想要的只是“姓名”和“生日”,您需要这样做:

    db.collection.find({},{ "_id": 0, "name": 1, "birthdate": 1 })
    

    或者这个:

    db.collection.find({},{ "_id": 0, "created": 0 })
    

    但不允许“混合”除“_id”以外的任何其他操作

    db.collection.find({},{ "_id": 0, "name": 1, "created": 0 })
    

    这也会产生错误。

    manual pages 中涵盖了所有这些内容。

    【讨论】:

    • 当我想要投影列表时,我总是通过_id:0?
    • @Sadikhasan 否。这只是为了排除默认情况下始终包含的“_id”字段。示例中提供了一个链接,可以更详细地说明。以及您应该花一些时间阅读的各种其他教程示例。
    • 知道他们为什么选择这个设计吗?允许在查询中“过多”冗长是有道理的
    • 我收到了这个错误,因为我的投影是{id:0, name:1}。我不小心删除了 ID 字段名称的下划线。应该是{_id:0, name:1}。我不理解 MongoDB 术语“BadValue Projection”,但这个答案证明了它所指的内容。
    【解决方案2】:

    它抛出错误“无法规范化查询:BadValue Projection 不能混合包含和排除。”因为您正在混合包含和排除。 1 代表包含,0 代表排除。您可以在查询中使用 0 或 1。因此,如果您希望仅查看 _id 和 name 字段,则可以使用: 1)包含:

                  db.testdata.find({}, {_id:1,name:1})
    

    或 2) 排除:

                  db.testdata.find({},{created:0})
    

    在上述两种情况下,它只会显示 _id 和 name 字段。

    【讨论】:

    • 默认 _id:1 总是包含在内?
    • 是的,1 代表包容性。所以它是字段名:inlusion(1)/exclusion(0)。
    【解决方案3】:

    我遇到了同样的问题。这意味着您不能告诉 MongoDB 选择特定字段并同时取消选择另一个字段。

    这是错误的,不能在选择选项中这样指定 错误:-投影不能混合包含和排除。

    reviewSchema.pre(/^find/, function (next) {
        this.populate({
            path: 'tour',
            select: 'name -__v'
        })
        next();
    });
    

    格式正确。

    reviewSchema.pre(/^find/, function (next) {
        this.populate({
            path: 'tour',
            select: 'name' // Removed -__v
        })
        next();
    });
    

    【讨论】:

    • 这是一个问题还是一个答案?
    【解决方案4】:

    用简单的话来描述解决方案,您可以告诉 MongoDB 您想要或不想要 MongoDB 提供的所有字段。

    这意味着在 select 方法中您必须仅提及必填或非必填字段。如下所示

    find({<!--query here--!>}).select({
    
            password: 0,
            allowed_ip: 0,
            username: 0,
            password: 0,
            __v: 0,
            _id: 0
        });

    它应该是零(排除/不需要)或一(包含/必填字段。)干杯!!!

    【讨论】:

      猜你喜欢
      • 2014-11-11
      • 2014-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-08
      相关资源
      最近更新 更多