Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何更改mongodb数组值的数据类型?_Mongodb_Types_Mongodb Query - Fatal编程技术网

如何更改mongodb数组值的数据类型?

如何更改mongodb数组值的数据类型?,mongodb,types,mongodb-query,Mongodb,Types,Mongodb Query,具有下列文件: { "_id" : 1.0000000000000000, "l" : [ 114770288670819.0000000000000000, NumberLong(10150097174480584) ]} 如何将“l”数组的第二个元素从NumberLong转换为平坦点(double),例如第一个元素 在mongo shell中加载文档 var doc=db.collection.find({u id:1.0000000000000000}) 使用pars

具有下列文件:

{
"_id" : 1.0000000000000000,
"l" : [ 
    114770288670819.0000000000000000, 
    NumberLong(10150097174480584)
]}
如何将“l”数组的第二个元素从NumberLong转换为平坦点(double),例如第一个元素

  • 在mongo shell中加载文档

    var doc=db.collection.find({u id:1.0000000000000000})

  • 使用
    parseFloat
    函数将字段显式转换为浮点数:

    doc.l[1]=parseFloat(doc.l[1])

  • 将文档保存回数据库

    db.collection.save(单据)


  • 要更新此值,您应该使用编程语言代码或一些使用java脚本的变通方法

    其他明智的做法是使用
    聚合
    ,在新集合中编写文档,如下所示:

    db.collectionName.aggregate({
        "$unwind": "$l"
    }, {
        "$project": {
            "l1": {
                "$divide": ["$l", 1] // divide by one or multiply by one 
            }
        }
    }, {
        "$group": {
            "_id": "$_id"
            , "l": {
                "$push": "$l1"
            }
        }
    }, {
        "$out": "newCollectionName" // write data in new collection
    })
    

    如果完成上述查询,则删除旧集合并使用此新集合

    另外,由于其他响应在执行中非常模糊,或者建议编写新集合或其他“不安全”操作,因此我认为您应该遵循的响应是正确的

    当您考虑到诸如“保持元素的顺序”和“不可能覆盖文档的其他更改”之类的所有考虑因素时,这并不是一个要解决的简单问题(尽管其他人不这么认为),这些都是生产系统中的重要考虑因素

    我能看到的唯一真正“安全(ish)”的方法是使用这样的构造(用于提高效率),它不可能(主要)吹走整个阵列并丢失任何“活动”写入:

    var bulk=db.collection.initializeOrderedBulkOp(),
    计数=0;
    db.collection.find({“l”:{“$type”:18}).forEach(函数(doc){
    bulk.find({“\u id”:doc.\u id}).updateOne({
    “$pull”:{“l”:{“$in”:doc.l}
    });
    计数++;
    如果(计数%1000==0){
    bulk.execute();
    bulk=db.collection.initializeOrderedBulkOp();
    }
    doc.l.map(函数(l,idx){
    返回{“l”:parseFloat(l.valueOf()),“idx”:idx}
    }).forEach(函数(l){
    bulk.find({“\u id”:doc.\u id}).updateOne({
    “$push”:{“l”:{“$each”:[l.l],“$position”:l.idx}
    });
    计数++;
    如果(计数%1000==0){
    bulk.execute();
    bulk=db.collection.initializeOrderedBulkOp();
    }
    });
    });
    如果(计数%1000!=0)
    bulk.execute();
    
    这意味着在需要时“批量”重写整个集合中的数据,但在单个样本上,结果是:

    {u id:1,“l”:[114770288670811910150097174480584]}
    
    因此,基本原理是,这将在您的集合中找到与当前匹配的
    NumberLong
    (BSON类型中为64位整数)文档,并按以下方式处理结果

  • 首先从数组中删除所有元素,其中元素的值已经存在

  • 转换所有元素并将它们添加回数组中它们所在的位置

  • 现在我说“safe(ish)”,因为考虑到您的文档很可能会被更新,并将新项目附加到数组中,或者文档确实发生了其他更改,这在很大程度上是“安全的”,这里有一个可能的问题

    如果这里的数组“值”不是真正的“唯一”,那么就没有真正的方法“拉”需要更改的项,并在它们最初出现的相同位置重新插入它们。无论如何,不是以“原子”和“安全”的方式

    因此,如图所示,此过程运行的“风险”是,“如果”您碰巧将一个与另一个现有元素具有相同值的新数组元素附加到数组中(并且仅当此情况发生在为文档读取光标之间和批量执行之前),则您运行“风险”从数组中完全删除该新项的

    但是,如果数组中的所有值对于每个文档都是完全“唯一”的,那么这将“完美”地工作,只需使用转换的类型将所有内容转换回原位,就不会有丢失其他文档更新或重要操作的“风险”

    这不是一个简单的陈述,因为逻辑要求你采取预防措施。但它不能在已经提到的限制内失败。它在您现在拥有的集合上运行,而不生成新的集合。

    使用parseFloat(doc.l[1]),它返回{}