C#MongoDB-根据ID从嵌套文档的数组中提取项目 [英] C# MongoDB - Pull an item from a nested document's array based on an ID

查看:69
本文介绍了C#MongoDB-根据ID从嵌套文档的数组中提取项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们一直在努力进行数小时的查询,这对我们来说似乎很容易,而且我们是通过Robo 3T进行的...现在的问题是将其转换为C#,但我们找不到方法,我们没有甚至不明白为什么它不起作用.

我们有以下查询:

db.getCollection('UserCollection').update({"User.Contacts._id": ObjectId("xxx")}, 
{
    $pull: {
        "User.Contacts": {
           "_id": {$in:[ObjectId("xxx")]}
    }
  }
})

现在我们的查询成功了,我们尝试用c#进行翻译,到目前为止,我们已经达到了这一点,我们真的不知道问题的根源.

public Task PullSocialInfoAsync(ObjectId contactId)
{
    var fieldName = nameof(UserContainer.User) + "." + nameof(UserContainer.User.Contacts) + "._id";
    var filter = NewFilterBuilder().Eq(fieldName, contactId);
    var update = new BsonDocument("$pull", new BsonDocument(nameof(UserContainer.User) + "." + nameof(UserContainer.User.Contacts), new BsonDocument("_id", new BsonDocument("$in", new BsonArray() { contactId }))));
    return GetCurrentCollection().FindOneAndUpdateAsync(filter, update);
}

在这里您看到FindOneAndUpdateAsync,但是我们也尝试了UpdateAsync,即使我们将字符串查询与Robo 3T上的内容匹配,我们也多次更改了BsonArray的初始化失败,但是没有成功. >

基于上述C#查询,我们得到以下输出: {{ "$pull" : { "User.Contacts" : { "_id" : { "$in" : [ObjectId("xxx")] } } } }}.最有趣的部分是,如果我复制粘贴..效果很好

有什么想法吗?

谢谢!

解决方案

如果我正确理解了您的要求,则需要pullFilter.

 var filter = Builders<UserCollection>.Filter.Where(u => u.User.Contacts.Any(c => c._Id == contactID));
var update = Builders<UserCollection>.Update.PullFilter(u => u.User.Contacts, c => c._Id == contactID);
collection.UpdateOne(filter, update);
 

这是测试任何人是否有兴趣的完整程序.

 using MongoDB.Entities; // PM> Install-Package MongoDB.Entities
using MongoDB.Bson;    
using System.Linq;

namespace StackOverflow
{
    public class Program
    {
        public class UserCollection : Entity
        {
            public User User { get; set; }
        }

        public class User
        {
            public Contact[] Contacts { get; set; }
        }

        public class Contact
        {
            public ObjectId _Id { get; set; }
        }

        private static void Main(string[] args)
        {
            new DB("test");

            var contactID = ObjectId.GenerateNewId();

            (new UserCollection
            {
                User = new User
                {
                    Contacts = new[]
                    {
                        new Contact { _Id = ObjectId.GenerateNewId()},
                        new Contact { _Id = contactID}
                    }
                }
            }).Save();

            DB.Update<UserCollection>()
              .Match(u => u.User.Contacts.Any(c => c._Id == contactID))
              .Modify(b => b.PullFilter(u => u.User.Contacts, c => c._Id == contactID))
              .Execute();
        }
    }
} 

We've been struggling for hours on a query that seems easy to us and that we made through Robo 3T... The issue is now to convert it into C# and we just can't find the way and we don't even understand why it doesn't work.

We have the following query:

db.getCollection('UserCollection').update({"User.Contacts._id": ObjectId("xxx")}, 
{
    $pull: {
        "User.Contacts": {
           "_id": {$in:[ObjectId("xxx")]}
    }
  }
})

Now that our query works, we try to translate it in c# and we reached that point so far and we don't really know where the issue can come from..

public Task PullSocialInfoAsync(ObjectId contactId)
{
    var fieldName = nameof(UserContainer.User) + "." + nameof(UserContainer.User.Contacts) + "._id";
    var filter = NewFilterBuilder().Eq(fieldName, contactId);
    var update = new BsonDocument("$pull", new BsonDocument(nameof(UserContainer.User) + "." + nameof(UserContainer.User.Contacts), new BsonDocument("_id", new BsonDocument("$in", new BsonArray() { contactId }))));
    return GetCurrentCollection().FindOneAndUpdateAsync(filter, update);
}

Here you see FindOneAndUpdateAsync, but we tried we UpdateAsync as well, also we change multiple time the initialisation of our BsonArray with no success, even if the query as string match what we have on Robo 3T

Based on the above C# query, we have that output: {{ "$pull" : { "User.Contacts" : { "_id" : { "$in" : [ObjectId("xxx")] } } } }}. The most interesting part is that if I copy paste.. well it works

Any ideas?

Thanks !

解决方案

if i understood your requirement correctly, a pullFilter is what you need.

var filter = Builders<UserCollection>.Filter.Where(u => u.User.Contacts.Any(c => c._Id == contactID));
var update = Builders<UserCollection>.Update.PullFilter(u => u.User.Contacts, c => c._Id == contactID);
collection.UpdateOne(filter, update);

here's the full program for testing if anybody's interested.

using MongoDB.Entities; // PM> Install-Package MongoDB.Entities
using MongoDB.Bson;    
using System.Linq;

namespace StackOverflow
{
    public class Program
    {
        public class UserCollection : Entity
        {
            public User User { get; set; }
        }

        public class User
        {
            public Contact[] Contacts { get; set; }
        }

        public class Contact
        {
            public ObjectId _Id { get; set; }
        }

        private static void Main(string[] args)
        {
            new DB("test");

            var contactID = ObjectId.GenerateNewId();

            (new UserCollection
            {
                User = new User
                {
                    Contacts = new[]
                    {
                        new Contact { _Id = ObjectId.GenerateNewId()},
                        new Contact { _Id = contactID}
                    }
                }
            }).Save();

            DB.Update<UserCollection>()
              .Match(u => u.User.Contacts.Any(c => c._Id == contactID))
              .Modify(b => b.PullFilter(u => u.User.Contacts, c => c._Id == contactID))
              .Execute();
        }
    }
}

这篇关于C#MongoDB-根据ID从嵌套文档的数组中提取项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆