C# 阵列上的mongoDB upsert

C# 阵列上的mongoDB upsert,c#,arrays,mongodb,mongodb-query,C#,Arrays,Mongodb,Mongodb Query,我的db模型是这样的 "clientId":"123456" "devices" : [{ "deviceId" : "123", "deviceType" : "ios", "notification" : true, } { "deviceId" : "321", "deviceType" : "android", "notification" : true, } ] 我传递给DB方法的c#模型有Cl

我的db模型是这样的

"clientId":"123456"
"devices" : 
[{
      "deviceId" : "123",
      "deviceType" : "ios",
      "notification" : true,
  }
  {
      "deviceId" : "321",
      "deviceType" : "android",
      "notification" : true,

  }
 ]
我传递给DB方法的c#模型有ClientId、DeviceId、DeviceType和notification。请注意,它没有设备阵列

我想要达到的行为

  • (工作)如果数据库中还没有ClientId,则使用传递的值在db中创建一个新记录,(devices数组将有一个元素)

  • 如果数据库中已找到ClientId,请根据以下规则更新记录:

    2.1如果设备数组不包含DeviceId,请使用传递的值向数组添加新元素

    2.2如果设备阵列已包含DeviceId,则更新元素的deviceType和通知

  • 我用的是c。谢谢你的帮助

    示例:给定数据库的上述状态,通过传递clientId:123456,deviceId 321 deviceType“kindle”,db将更改为通知“false”

    "clientId":"123456"
    "devices" : 
    [{
          "deviceId" : "123",
          "deviceType" : "ios",
          "notification" : true,
      }
      {
          "deviceId" : "321",
          "deviceType" : "kindle",
          "notification" : false,
    
      }
     ]
    

    您正在寻找一个典型的位置运算符情况:

    db.coll.update
    (
        {
            "clientId":"123456","devices.deviceId":"321"
        },
        {
            $set:
            {
                "devices.$.deviceType":"kindle","devices.$.notification":"false"
            }
        }
    )
    

    您需要更新数组中匹配的元素,$可以为您执行此操作,这样您就可以在数组中找到具有特定元素的文档,并使用位置运算符$来“记住”要更新的元素。

    这并不像您想象的那么简单,事实上,有趣的是,你把你的分析分为三个部分。因为,你猜怎么着?这正是你必须做的。让我们考虑以下步骤:

    1.如果文档不存在,请插入文档
    db.collection.update(
    { 
    “客户ID”:“123456”
    },
    {
    “$setOnInsert”:{
    “客户ID”:“123456”,
    “设备”:[{
    “设备ID”:“321”,
    “设备类型”:“kindle”,
    “通知”:虚假
    }]
    }
    },
    {“upsert”:true}
    )
    
    因此,您要做的是在当前不存在“clientId”的地方插入一个新文档。这可以作为“向上插入”来完成,以避免可能的唯一关键点冲突,即使在没有“唯一”约束的情况下,也可以使用“向上插入”来确保仅在未找到“新”文档时创建该文档。这里还有
    $setOnInsert
    ,因为您不想对此时“找到”的文档执行任何操作

    请注意,没有尝试匹配数组中的元素。这是因为您可能不想仅仅因为现有文档没有“that”数组元素而“创建”新文档。这让我们进入下一步

    2.在文档存在的地方更新文档的内容
    db.collection.update(
    { 
    “客户ID”:“123456”,
    “设备”:{“$elemMatch”:{“设备ID”:“321”}
    },
    {
    “$set”:{
    “设备.$.deviceType”:“kindle”,
    “设备.$.notification”:false
    }
    }
    )
    
    现在,您需要实际尝试“匹配”文档中的“clientId”,该“clientId”在数组中包含一个元素,该元素也与您要查找的“deviceId”匹配。因此,通过指定要匹配的条件,可以使用positional
    $
    操作符将字段设置为“匹配”位置

    如上所述,这要么匹配一件事情,要么什么都不匹配,因此要么更新完成了,要么没有。这就转到了级联的最后一部分:

    3.将数组元素添加到不存在的位置
    db.collection.update(
    { 
    “客户ID”:“123456”
    },
    {
    “$addToset”:{“设备”:{
    “设备ID”:“321”,
    “设备类型”:“kindle”,
    “通知”:虚假
    }}
    }
    )
    
    因此,这是非常重要的最后阶段。原因是,如果前面的操作之一确实“创建”或“更新”了现有文档,那么在此处使用
    $addToSet
    可以确保您没有使用相同的“deviceId”但其他不同的值将另一个文档“推送”到数组中。如果这些阶段中有一个有效,那么这将看到该元素的所有值都已存在,并且不会再添加另一个值

    如果您尝试以不同的顺序执行此操作,那么在您呈现的情况下,数组中会有两个文档,它们具有相同的“deviceId”,但“deviceType”和“notification”的值不同。这就是为什么它排在最后

    结论 因此,不幸的是,没有简单的方法将这些操作组合为一个操作。运算符根本不存在,因此这可以在一条语句中完成,因此您必须执行三个更新操作才能完成所需的操作。同样如前所述,这些更新的应用程序的顺序非常重要,以便您获得所需的结果

    虽然目前的“生产”版本中尚不存在这种情况,但即将发布的版本(2.6及更高版本,截至编写时)确实有办法使用新语法来处理这些请求,以便:

    db.runCommand(
    “更新”:“收集”,
    “更新”:[
    { 
    “q”:{“clientId”:“123456”},
    “u”:{
    “$setOnInsert”:{
    “客户ID”:“123456”,
    “设备”:[{
    “设备ID”:“321”,
    “设备类型”:“kindle”,
    “通知”:虚假
    }]
    },
    “向上插入”:正确
    },
    {
    “q”:{
    “客户ID”:“123456”,
    “设备”:{“$elemMatch”:{“设备ID”:“321”}
    },
    “u”:{
    “$set”:{
    “设备.$.deviceType”:“kindle”,
    “设备.$.notification”:false
    }
    }
    },
    {
    “q”: