简体   繁体   English

MongoDb / C#过滤器并获取所有子文档

[英]MongoDb / C# filter and get all subdocuments

I'm having difficulties querying a Mongo-DB collection. 我在查询Mongo-DB集合时遇到困难。

The document I'm using 我正在使用的文件

public class Customer
{
    public ObjectId Id { get; set; }

    public int CustomerId { get; set; }

    public List<Address> Addresses { get; set; }
}

public class Address
{
    public string Name { get; set; }
}

Some sample-Data 一些样本数据

{
    CustomerId: 2,
    Addresses: [
        {
            Name: "Daniel"
        },
        {
            Name: "Eric"
        },
        {
            Name: "Dan"
        }
        ]
}

I now want to query the documents by the CustomerId and filter some of the Addresses-values to return all Addresses with a Name like %Dan%. 现在,我想通过CustomerId查询文档,并过滤一些Addresses-values以返回名称为%Dan%的所有Addresses。 As the address-collection can be huge I want to already filter those addresses at query-time 由于地址集合可能非常庞大,我想在查询时已经过滤掉这些地址

var mdb = mongoClient.GetDatabase("test");
var collection = mdb.GetCollection<WebApi>("Customer");
var builder = Builders<Customer>.Filter;
var searchTerm = "Dan";

When querying like that it works but it holds all addresses: 像这样查询时,它可以工作,但它包含所有地址:

var filter = builder.And(builder.Eq("InstallationId", 2),
                         builder.Regex("Addresses.Name", new BsonRegularExpression(".*" + searchTerm + ".*", "i")))
var result = collection.Find(filter).FirstOrDefault();

What I'd like to get is: 我想要得到的是:

[
    {
        Name: "Daniel"
    },
    {
        Name: "Dan"
    }
]

or 要么

{
    CustomerId: 2,
    Addresses: [
        {
            Name: "Daniel"
        },
        {
            Name: "Dan"
        }
        ]
}

I also tried several approaches with Aggregate/Match/Project but can't get it to work. 我还尝试了几种使用Aggregate / Match / Project的方法,但无法使其正常工作。 "AsQueryable" also does not work as IndexOf is not implemented on the driver. 由于未在驱动程序上实现IndexOf,因此“ AsQueryable”也不起作用。

collection.AsQueryable().Where(x => x.CustomId == 2).SelectMany(x =>
                x.Addresses.Where(a => a.Name.IndexOf(searchTerm, StringComparison.InvariantCultureIgnoreCase) >= 0).ToList();

Used Versions: 使用的版本:

  • MongoDB.Driver v 2.6.1 (also Bson) MongoDB.Driver v 2.6.1(也是Bson)
  • .Net Framework 4.5.2 .Net Framework 4.5.2

This should get you going: 这应该可以帮助您:

var result = collection
    .Aggregate()
    .Match(c => c.CustomerId == 2)
    .Project(c => new
        {
            c.CustomerId,
            Addresses = c.Addresses.Where(a => a.Name.IndexOf(searchTerm) != -1)
        })
    .ToList();

The driver will translate this into: 驱动程序会将其转换为:

db.Customer.aggregate([{
    $match: { CustomerId: 2 }
}, {
    $project: {
        CustomerId: "$CustomerId",
        Addresses: {
            $filter: {
                input: "$Addresses",
                as: "a",
                cond: {
                    $ne: [ { $indexOfBytes: [ "$$a.Name", "Dan" ] }, -1 ]
                }
            }
        },
        _id: 0
    }
}])

For the case-insensitive version, there will be a the option to use $regex at some stage in the future (see https://jira.mongodb.org/browse/SERVER-11947 ). 对于不区分大小写的版本,将来可以选择使用$ regex(请参阅https://jira.mongodb.org/browse/SERVER-11947 )。 However, what you can do just now is use ToUpper() : 但是,您现在可以使用ToUpper()

var result = collection
    .Aggregate()
    .Match(c => c.CustomerId == 2)
    .Project(c => new
        {
            c.CustomerId,
            Addresses = c.Addresses.Where(a => a.Name.ToUpper().IndexOf(searchTerm.ToUpper()) != -1)
        })
    .ToList();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM