Py学习  »  chridam  »  全部回复
回复总数  2
7 年前
回复了 chridam 创建的主题 » mongodb中的条件更新多?[副本]

对于MongoDB 3.6及更新版本:

这个 $expr $strLenCP 运算符检查字符串的长度,如下所示:

db.usercollection.find({ 
    "name": { "$exists": true },
    "$expr": { "$gt": [ { "$strLenCP": "$name" }, 40 ] } 
})

对于MongoDB 3.4及更新版本:

$redact 管道运算符,允许您使用 $cond 操作员和使用特殊操作 $$KEEP 在逻辑条件为真或 $$PRUNE 删除条件为假的文档。

这个操作类似于 $project 选择集合中的字段并创建新字段的管道,该字段保存逻辑条件查询的结果,然后 $match $修订 使用单管道级,效率更高。

至于逻辑条件,有 String Aggregation Operators $strLenCP公司 运算符检查字符串的长度。如果长度是 $gt 一个指定的值,则这是一个真正的匹配,并且文档被“保留”。否则将被“修剪”并丢弃。


db.usercollection.aggregate([
    { "$match": { "name": { "$exists": true } } },
    {
        "$redact": {
            "$cond": [
                { "$gt": [ { "$strLenCP": "$name" }, 40] },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    },
    { "$limit": 2 }
])

如果使用 $where ,请尝试不带括号的查询:

db.usercollection.find({$where: "this.name.length > 40"}).limit(2);

db.usercollection.find({name: {$type: 2}, $where: "this.name.length > 40"}).limit(2); 

或:

db.usercollection.find({name: {$exists: true}, $where: "this.name.length > 
40"}).limit(2); 

MongoDB计算非- $哪里 之前的查询操作 表达式与非- $哪里 查询语句可以使用索引。更好的性能是将字符串的长度存储为另一个字段,然后可以对其进行索引或搜索;应用 $哪里 $哪里 当您无法以任何其他方式构造数据时,或者当您正在处理


一种避免使用 接线员是 $regex 接线员。考虑以下搜索

db.usercollection.find({"name": {"$type": 2, "$regex": /^.{41,}$/}}).limit(2); 

注意 docs :

针对索引中的值的表达式,该值可以比 收集扫描。如果 表达式是前缀表达式,这意味着 范围从该前缀开始,并且仅与 在该范围内的索引。

如果正则表达式以 插入符号 (^) 或左锚 (\A) ,后跟一个简单的字符串 符号。例如,regex /^abc.*/ 将通过 仅与以开头的索引中的值匹配 abc

另外,当 /^a/, /^a.*/, /^a.*$/ 字符串有不同的性能特征。所有这些 如果存在适当的索引,表达式将使用索引;但是, /^a.*/ ,和 比较慢。 /^a/ 扫描后可以停止 匹配前缀。

6 年前
回复了 chridam 创建的主题 » MongoDB-找到一个并添加新属性

你需要在这里做两次手术。第一种方法是从数据库中获取与JSON数组中的文档匹配的文档数组。从列表中比较 'product_quantity' 键,如果有更改,则使用产品id和数量更改创建新的对象数组。

第二个操作将是一个更新,它使用这个新数组,其中包含每个匹配产品的数量变化。

有了这个新的更新产品属性数组,最好使用批量更新来遍历列表并发送 对服务器的每一个更新请求都可能在计算上代价高昂。

考虑使用 bulkWrite 模型上的方法。它接受一个写操作数组并执行其中的每一个典型的更新操作 对于您的用例,将具有以下结构

{ updateOne :
    {
    "filter" : <document>,
    "update" : <document>,
    "upsert" : <boolean>,
    "collation": <document>,
    "arrayFilters": [ <filterdocument1>, ... ]
    }
}

因此,您的操作将遵循以下模式:

(async () => {

    let bulkOperations = []
    const ids = products.map(({ id }) => id)
    const matchedProducts =  await ProductDatabase.find({ 
        '_id': { '$in': ids }
    }).lean().exec()

    for(let product in products) {
        const [matchedProduct, ...rest] = matchedProducts.filter(p => p._id === product.id)
        const { _id, product_quantity } = matchedProduct
        const changeInQuantity = product.product_quantity - product_quantity

        if (changeInQuantity !== 0) {
            const stamps = { [(new Date()).getTime()] : changeInQuantity }

            bulkOperations.push({
                'updateOne': {
                    'filter': { _id },
                    'update': { 
                        '$inc': { 'product_quantity': changeInQuantity },
                        '$push': { stamps }
                    }
                }
            })
        }
    }

    const bulkResult = await ProductDatabase.bulkWrite(bulkOperations)
    console.log(bulkResult)

})()