복붙노트

[MONGODB] MongoDB의 C # 드라이버 복귀 만 배열 하위 문서를 일치

MONGODB

MongoDB의 C # 드라이버 복귀 만 배열 하위 문서를 일치

나는이 형식의 문서가 :

{
    _id: ...,
    myArray: [{other: stuff}, {other: stuff}, ...],
    ...
}

나는에서 myArray의 하위 문서에서 _id 또는 필드 값처럼, 어떤 일을 일치하는 요소를 찾고 싶어요.

나는 문서를 반환하고 싶지만, 필터링 된 경우 MyArray 만 일치하는 하위 문서가 존재하는 곳.

나는 투사를하고이 같은 일치하는 요소를 포함하려고 :

_mongoContext.myDocument
    .Find(x => x.id == id & x.myArray.Any(y => myList.Contains(t.other)))
    .Project<myModel>(Builders<myModel>.Projection.Include("myArray.$"))

이것은 생각 만 나는 (I 반환 된 문서에 존재하는 쿼리와 일치하는 모든 하위 문서를 원하는) 원하는하지 않은 모든 문서 대신에 myArray에 일치하는 첫 번째 요소를 반환해야합니다.

어쨌든 그것은 심지어는 위치 투사 쿼리 문서 오류 일치하지 않는군요, 작동하지 않았다. 내가 FindOne를 사용하지 않는 때문에 어쩌면입니까?

어떤 경우에는, 어떻게 내가 무엇을 찾고 달성 할 수 있습니까? (굵게 질문을 참조)

해결법

  1. ==============================

    1.일반적으로 당신은 중첩 된 배열을 필터링 할 집계 프레임 워크에서 $ 필터를 사용해야합니다. 그러나 그 사용하여 MongoDB를 .NET 드라이버 및 된 IQueryable 인터페이스를 달성 할 수있는 쉬운 방법이있다.

    일반적으로 당신은 중첩 된 배열을 필터링 할 집계 프레임 워크에서 $ 필터를 사용해야합니다. 그러나 그 사용하여 MongoDB를 .NET 드라이버 및 된 IQueryable 인터페이스를 달성 할 수있는 쉬운 방법이있다.

    간단한 모델을 고려 :

    public class MyModel
    {
        public string _id { get; set; }
        public IEnumerable<MyNestedModel> myArray { get; set; }
    }
    
    public class MyNestedModel
    {
        public string other { get; set; }
    }
    

    데이터를 다음과 같은 :

    var m = new MyModel()
    {
        _id = "1",
        myArray = new List<MyNestedModel>() {
            new MyNestedModel() {  other = "stuff" },
            new MyNestedModel() { other = "stuff" },
            new MyNestedModel() { other = "stuff2" } }
    };
    
    Col.InsertOne(m);
    

    당신은 단순히 컬렉션에 .AsQueryable ()를 호출 할 수 있습니다 다음은 $ 필터 MongoDB를 드라이버에 의해 번역됩니다 LINQ 쿼리를 작성할 수, 시도 :

    var query = from doc in Col.AsQueryable()
                where doc._id == "1"
                select new MyModel()
                {
                    _id = doc._id,
                    myArray = doc.myArray.Where(x => x.other == "stuff")
                };
    
    var result = query.ToList();
    

    편집하다:

    또는 당신은 원시 문자열로 $ 필터 부분을 쓴 후 .Aggregate () 메서드를 사용합니다. 당신이없는이 방법을 사용하여 모든 속성 그러나 단점이 단지 문자열이기 때문에 당신이 유형의 안전을 잃고 있다는 점이다 "지도"를, 시도 :

    var addFields = BsonDocument.Parse("{ \"$addFields\": { myArray: { $filter: { input: \"$myArray\", as: \"m\", cond: { $eq: [ \"$$m.other\", \"stuff\" ] } }  } } }");
    
    var query = Col.Aggregate()
                   .Match(x => x._id == "1")
                   .AppendStage<MyModel>(addFields);
    

    $ addFields 기존 필드를 덮어 여기에 사용됩니다.

  2. from https://stackoverflow.com/questions/53232771/mongodb-c-sharp-driver-return-only-matching-sub-documents-in-array by cc-by-sa and MIT license