web-dev-qa-db-ja.com

MongoDb C#ドライバーはフィールド値で配列内のアイテムを検索します

私はチェックする方法が値が単純な配列に含まれていることを見つけました:

var filter = Builders<Post>.Filter.AnyEq(x => x.Tags, "mongodb");

しかし、具体的なフィールドで多くのフィールドを持つ複雑なアイテムを見つける方法は? BsonDocumentビルダーを使用したドット表記アプローチを使用してそれを記述する方法を見つけましたが、型付きラムダ表記でどのように行うことができますか?

pd

ある種のと思う

builderInst.AnyIn(p => p.ComplexCollection.Select(ml => ml.Id), mlIds)

しかし、今すぐ確認することはできません、誰でも助けることができますか?

25

ElemMatchがあります

var filter = Builders<Post>.Filter.ElemMatch(x => x.Tags, x => x.Name == "test");
var res = await collection.Find(filter).ToListAsync()
34
rnofenko

$elemMatch演算子が必要です。 Builders<T>.Filter.ElemMatchまたはAny式を使用できます。

Find(x => x.Tags.Any(t => t.Name == "test")).ToListAsync()

http://mongodb.github.io/mongo-csharp-driver/2.0/reference/driver/expressions/#elemmatch

5
hansmaad

以下は、配列から単一の複雑なアイテムを返す例です(MongoDB.Driver v2.5.0を使用)。

シンプルデータモデル

public class Zoo
{
    public List<Animal> Animals { get; set; }
}

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

オプション1(集計)

public Animal FindAnimalInZoo(string animalName)
{
    var zooWithAnimalFilter = Builders<Zoo>.Filter
        .ElemMatch(z => z.Animals, a => a.Name == animalName);

    return _db.GetCollection<Zoo>("zoos").Aggregate()
        .Match(zooWithAnimalFilter)
        .Project<Animal>(
            Builders<Zoo>.Projection.Expression<Animal>(z => 
                z.Animals.FirstOrDefault(a => a.Name == animalName)))
        .FirstOrDefault(); // or .ToList() to return multiple
}

オプション2(フィルターとLinq)これは私にとって約5倍遅い

public Animal FindAnimalInZoo(string animalName)
{
    // Same as above
    var zooWithAnimalFilter = Builders<Zoo>.Filter
        .ElemMatch(z => z.Animals, a => a.Name == animalName);

    var zooWithAnimal = _db.GetCollection<Zoo>("zoos")
        .Find(zooWithAnimalFilter)
        .FirstOrDefault();

    return zooWithAnimal.Animals.FirstOrDefault(a => a.Name == animalName);
}
4
JBond

C#ドライバーの2.4.2リリースの時点では、IFindFluentインターフェイスを使用して配列要素のクエリを実行できます。 ElemMatchは文字列の配列で直接使用することはできませんが、検索インターフェイスは単純型または複合型(例: 'Tags.Name')で動作し、強く型付けされます。

            FilterDefinitionBuilder<Post> tcBuilder = Builders<Post>.Filter;
            FilterDefinition<Post> tcFilter = tcBuilder.Eq("Tags","mongodb") & tcBuilder.Eq("Tags","asp.net");
               ...
            await myCollection.FindAsync(tcFilter);

Linqドライバーは集計フレームワークを使用しますが、集計演算子を使用しないクエリの場合、検索は高速です。

これは以前のバージョンのドライバーでは壊れているため、元の投稿の時点では答えが得られなかったことに注意してください。

2
Aaron Newman