Mongodb $ setOnInsert无法使用$ max和$ min

时间:2015-07-09 17:47:25

标签: javascript node.js mongodb mongoose mongodb-query

我有以下查询在没有$max$min的情况下正常工作,但是,当包含$max$min时,没有任何事情发生?

Summary.update({
  productId: _product._id,
},{
  $addToSet: { 
    attrs: _variant.attrs,
    vars: {
      variantId: _variant._id,
      title: _variant.title,
      imgs: _variant.imgs,
    } 
  },
  $max: { 'price.highest': _price.highest },
  $min: { 'price.lowest': _price.lowest },
  $setOnInsert: self.summary
},{
  upsert: true
},function(err,update){
  ...
});

非常感谢任何想法。

感谢。

1 个答案:

答案 0 :(得分:3)

你的查询确实附带了警告,所以它真的只能解释会出现什么问题。

首先,您的MongoDB服务器版本必须至少为2.6.x或更高版本,才能使$min$max更新运算符可用。

现在考虑基本的测试条件:

> db.test.update(
    { "a": 1 },
    { 
        "$setOnInsert": { "b": 2 },
        "$min": { "c": 1 }, 
        "$max": { "d": 1 } 
    },
    { "upsert": true }
  )
WriteResult({
    "nMatched" : 0,
    "nUpserted" : 1,
    "nModified" : 0,
    "_id" : ObjectId("559f114dbe78f212535e2f5f")
})

在第一次执行时,由于没有匹配值为“a”的数据,因此在集合中创建新对象时执行upsert

{
    "_id" : ObjectId("559f114dbe78f212535e2f5f"),
    "a" : 1,
    "d" : 1,
    "c" : 1,
    "b" : 2,
}

现在,如果您更改$min$max的值,则预期的行为是修改值在约束范围内的字段,如下所示:

> db.test.update(
    { "a": 1 },
    { 
        "$setOnInsert": { "b": 3 }, 
        "$min": { "c": 2 },
        "$max": { "d": 2 }
    },
    { "upsert": true }
  )
  WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

由于$min的值大于存储值,因此不会更改此字段。但是,$max的值大于存储值并且已修改。 $setOnInsert中有一个不同的值,但这不会影响数据,因为此次操作不是upsert

{
    "_id" : ObjectId("559f114dbe78f212535e2f5f"),
    "a" : 1,
    "d" : 2,
    "c" : 1,
    "b" : 2
}

如果您发出的语句具有$min$max的相同值,或者除了分别为“较低”或“较高”值的约束外,则不会更新任何内容:

db.test.update(
    { "a": 1 },
    { 
        "$setOnInsert": { "b": 3 },
        "$min": { "c": 2 }, 
        "$max": { "d": 2 } 
    },
    { "upsert": true }
)
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 0 })

这是运营商在此上下文中的预期行为。当然,如果您在尚不存在的字段上提交$min$max,则该字段会添加到具有指定值的文档中,就像使用$set或{{ 1}}或类似的。

因此要么您要分配不符合更新要求的值,要么支持的服务器和/或驱动程序版本无法处理运算符。这些都是您需要检查的内容,以了解您认为自己没有获得预期结果的原因。

作为旁注,请注意您也知道$push对您的期望。以类似的方式,如果已存在完整对象,则不会修改任何内容。但是,如果您有一个具有各种键的对象,那么更改这些值中的任何一个都会使整个对象“唯一”,并且将添加一个新成员。如果你的意思是做其他事情,比如只有“一个”键来包含一个独特的vallue thene,你需要应用其他逻辑,而不能简单地使用$addToSet来处理它。

此外,除了上述测试条件之外,这里还有一个完整列表,您可以使用node和mongoose运行。这是针对MongoDB 3.x和mongoose 4.0.6进行测试的:

$addToSet