Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/396.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
Javascript 在for循环中使用set if extist或put if notes';T_Javascript_Node.js_Mongodb_Mongoose - Fatal编程技术网

Javascript 在for循环中使用set if extist或put if notes';T

Javascript 在for循环中使用set if extist或put if notes';T,javascript,node.js,mongodb,mongoose,Javascript,Node.js,Mongodb,Mongoose,我在for a循环中尝试将findOneAndUpdate与mongoose一起使用时遇到了并发性问题。 不要把重点放在给出的例子上,而只放在它的方法上。 假设我有这个模式: var PlayerSchema = new Schema({ playername: String, playerstats:[{ matchNumber: Number, goals: { type: Number, def

我在for a循环中尝试将findOneAndUpdate与mongoose一起使用时遇到了并发性问题。 不要把重点放在给出的例子上,而只放在它的方法上。 假设我有这个模式:

var PlayerSchema = new Schema({
    playername: String,
    playerstats:[{
        matchNumber: Number,
        goals: {
            type: Number,
            default: 0
        }
    }]
})
假设我有一年的数组,我想用另一个用for循环迭代创建的数组来更新目标,我想做的是为x=0到5创建一个for循环,其中x是匹配数,分数[x]表示该匹配的目标数(去年)。我想在玩家文档中查看匹配号是否存在,如果它存在,我会使用findOneAndUpdate和$set设置分数[x],但它不存在。我想使用$push和分数[x]创建它。让我们给出最容易理解的代码(“马拉多纳”将是我们的球员名字):

但我得到的是:

{
    playername: "Maradona",
    playerstats:[
        {
            matchNumber: 0,
            goals: 1
        },
        {
            matchNumber: 0,
            goals: 0
        },
        {    
            matchnumber: 1,
            goals: 11
        },
        {    
            matchnumber: 1,
            goals: 10
        },
        {
            matchNumber: 2,
            goals: 21
        },
        {
            matchNumber: 2,
            goals: 20
        },
        {
            matchNumber: 3,
            goals: 31
        },
        {
            matchNumber: 3,
            goals: 30
        },
        {
            matchNumber: 4,
            goals: 41
        },
        {
            matchNumber: 4,
            goals: 40
        }
}
或者是它们的混合体。 这是因为代码将尝试使用$set创建findOneAndUpdate,当找不到matchNumber(matchfound==null)时,而不是使用$push执行findOneAndUpdate来创建它,它将继续迭代,因此将尝试使用k=1的值执行相同的操作(澄清的第二年)并且需要再次移动到带有$push的findOneAndUpdate,因为找不到它,所以创建了分数=(x*10)+k的值,然后,它将返回并生成带有$push和分数=x*10的findOneAndUpdate。我知道这是它的正常工作,因为单线程,但我真的需要有理想的输出。
感谢大家,很抱歉读了这么长时间。

问题在于
findOneAndUpdate
是异步的。for循环中的每个迭代调用Player.findOneAndUpdate,并向其传递回调函数。findOneAndUpdate调用立即返回,循环继续进行下一次迭代

在将来的某个时候,对mongo的查询将完成,并使用返回值调用回调,因为存在多个分段异步调用,所以它们完成的顺序没有严格定义

您可以尝试在每次调用findOneAndUpdate时使用
wait
,使它们同步,这将序列化请求

如果您使用的是MongoDB 4.2,则可以使用update的管道形式,在一条语句中插入和更新数组元素:

.update(
         {playername: "Maradona"},
         [{$set:{
             playerstats:{
                 $concatArrays:[
                     {$filter:{
                         input:"$playerstats",
                         cond:{$ne:["$$this.matchNumber",x]}
                     }},
                     [{matchNumber: x, goals: scores[x] }]
                 ]
             }
          }}]
)
为了确保以正确的顺序应用这些操作,您可以构建和排列要应用的所有操作,如:

[
  {updateOne:{
    filter: {playername: "Maradona"},
    update: [{$set:{
             playerstats:{
                 $concatArrays:[
                     {$filter:{
                         input:"$playerstats",
                         cond:{$ne:["$$this.matchNumber",0]}
                     }},
                     [{matchNumber: 0, goals: 1 }]
                 ]
             }
          }}]
 }},
 {updateOne:{
    filter: {playername: "Maradona"},
    update: [{$set:{
             playerstats:{
                 $concatArrays:[
                     {$filter:{
                         input:"$playerstats",
                         cond:{$ne:["$$this.matchNumber",1]}
                     }},
                     [{matchNumber: 1, goals: 11 }]
                 ]
             }
          }}]
 }}
然后使用
ordered=true
选项将该数组传递给


另外请注意,如果您能够构建一个包含所有需要更新的分数的数组,您可以使用类似的语句在一次操作中更新单个玩家的所有分数,这应该会有更好的表现。

非常感谢您的建议。很抱歉,我完全不明白你是怎么解决的。您是否建议将findOneAndUpdate替换为数组创建?你建议什么时候给我打电话?我如何确保只有在阵列完成时才会调用它,并且它不会“混合”2019年的值和2020年的值?其想法是在不调用服务器的情况下构建updateOne对象的阵列。然后使用
bulkWrite
一次性将阵列发送到服务器,并在选项中指定
ordered:true
,以便服务器按照更新在阵列中出现的顺序应用更新。如果您需要确保2019年后2020年的处理完成,请按照您希望的处理顺序将它们全部构建到同一阵列中。感谢clearify@Joe。由于数组是以二进制方式填充的,我已经解决了将其传递给updateScores函数的问题,然后检查它是否是数组中的最后一个元素,如果是,则我进行更新,否则将跳过它。因此,由于years数组在所有被调用的UpdateStores函数的迭代之前被完全填充,所以它将只生成最后一个(我想要的唯一一个)。谢谢大家,这些都是对未来的宝贵建议!
.update(
         {playername: "Maradona"},
         [{$set:{
             playerstats:{
                 $concatArrays:[
                     {$filter:{
                         input:"$playerstats",
                         cond:{$ne:["$$this.matchNumber",x]}
                     }},
                     [{matchNumber: x, goals: scores[x] }]
                 ]
             }
          }}]
)
[
  {updateOne:{
    filter: {playername: "Maradona"},
    update: [{$set:{
             playerstats:{
                 $concatArrays:[
                     {$filter:{
                         input:"$playerstats",
                         cond:{$ne:["$$this.matchNumber",0]}
                     }},
                     [{matchNumber: 0, goals: 1 }]
                 ]
             }
          }}]
 }},
 {updateOne:{
    filter: {playername: "Maradona"},
    update: [{$set:{
             playerstats:{
                 $concatArrays:[
                     {$filter:{
                         input:"$playerstats",
                         cond:{$ne:["$$this.matchNumber",1]}
                     }},
                     [{matchNumber: 1, goals: 11 }]
                 ]
             }
          }}]
 }}