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

时间:2015-03-09 14:59:38

标签: c# mongodb mongodb-.net-driver

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

如果文档如下所示:

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

我希望能够说"寻找具有subdoc.key == 5和subdoc.value ==" ade&#34 ;;将subdoc.isActive设置为false并设置subdoc.deleteAt =当前db时间戳。使用这样的结果文档:

{   
    "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数据库实例生成带时间戳的值。我对这种方法非常满意。

2 个答案:

答案 0 :(得分:0)

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

以下是查询Parent数据库中test集合的一小段代码。 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字段(如果它包含值)。我们还在代码中使用了一个可空的DateTime对象,以便在需要时允许空值存储。

 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; } 
}

答案 1 :(得分:0)

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