在MongoDb中,如何在数组属性中的对象上设置值

本文关键字:对象 设置 数组 MongoDb 属性 | 更新日期: 2024-11-07 20:53:18

我的目标是在文档数组中的特定对象上放置一个"删除时间"时间戳。

如果文档如下所示:

{   
    "subdoc": [
        {
            "key": 1,
            "value": "abc",
            "isActive": true
        },
        {
            "key":5,
            "value": "ade",
            "isActive":true
        }
    ]
}

我希望能够说"查找具有子文档的文档.key == 5 和 subdoc.value == "ade";将 subdoc.isActive 设置为 false,并将 subdoc.deleteAt = 当前数据库时间戳设置为。结果文档如下所示:

{   
    "subdoc": [
        {
            "key": 1,
            "value": "abc",
            "isActive": true
        },
        {
            "key":5,
            "value": "ade",
            "isActive": false,
            "deletedAt": Timestamp(1425911075,1)
        }
    ]
}

这可行吗?

更新:在进一步审查了 mongo 文档后,这似乎可以使用"$(更新)"运算符。 这让我得到了我需要的东西,但我希望使用 C# 驱动程序以一种不那么神奇的字符串方式来做到这一点?

我的工作查找/更新如下所示:

// find
{
    "subdoc.key":"2",
    "subdoc.value":"ade"
}
// update
{   
    "$currentDate": {
        "subdoc.$.deleteAt": {
            "$type": "timestamp"
        }
    }
}
更新

:我应该澄清一下,这个更新的时间戳字段用于在具有高事务量的负载平衡环境(多个 Web 服务器、多个工作进程和一个 mongo 集群)中由许多有时连接的移动客户端进行同步,这使得此时间戳具有单点事实至关重要,在应用程序的上下文中是逻辑顺序的, 并且尽可能高精度(几分之一秒)。 否则,同步中可能会丢失记录。

目前,我正在使用上述方法来确保 mongo 数据库实例生成时间戳值。 我对这种方法非常满意。

在MongoDb中,如何在数组属性中的对象上设置值

可以使用

C# 驱动程序将 mongo 实体包装在 C# 对象中。然后在代码中,可以使用 linq 查询数据库并根据需要更新对象。然后只需将它们保存到数据库即可保留更改。

下面是一小段代码,用于查询 test 数据库中的 Parent 集合。C# 驱动程序作为扩展提供AsQueryable允许我们直接在 Linq 中编写查询。然后,驱动程序将自动生成所需的查询,并针对集合执行该查询。

下面的示例在subdoc列表中查找key字段值为 5 的任何子文档

如果找到任何内容,它将更新 deletedAt 日期,然后将其保存回数据库。

var client = new MongoClient();
var database = client.GetServer().GetDatabase("test");
var parentCollection = database.GetCollection<Parent>("Parent");
var parent = parentCollection.AsQueryable().FirstOrDefault(p => p.subdoc.Any(f => f.key == 5));
if (parent != null)
{
    var fooList = parent.subdoc.Where(f => f.key == 5);
    foreach (var foo in fooList)
    {
        foo.deletedAt = DateTime.UtcNow;
    }
}
parentCollection.Save(parent);

下面是用于映射到 Mongo 文档的两个 c# 实体。我们可以使用 mongo c# 驱动程序的 [BsonIgnoreIfNull] 属性来序列化包含值的deletedAt字段。我们还在代码中使用可为 null 的 DateTime 对象,以允许在需要时存储 null。

 public class Foo 
{
    [BsonId]
    public ObjectId Id { get; set; }
    public int key { get; set; }
    public string value { get; set; }
    public bool isActive { get; set; }
    [BsonIgnoreIfNull]
    public DateTime? deletedAt { get; set; }
}
public class Parent
{
    [BsonId]
    public ObjectId Id { get; set; }
    public List<Foo> subdoc { get; set; } 
}

查看最新更新。位置运算符和$currentDate运算符的组合符合我的目的。