[MONGODB] C 번호로 집계 $ 조회
MONGODBC 번호로 집계 $ 조회
나는 다음과 같은 MongoDB의 쿼리 작업이 :
db.Entity.aggregate(
[
{
"$match":{"Id": "12345"}
},
{
"$lookup": {
"from": "OtherCollection",
"localField": "otherCollectionId",
"foreignField": "Id",
"as": "ent"
}
},
{
"$project": {
"Name": 1,
"Date": 1,
"OtherObject": { "$arrayElemAt": [ "$ent", 0 ] }
}
},
{
"$sort": {
"OtherObject.Profile.Name": 1
}
}
]
)
이것은 다른 집합으로부터 매칭 오브젝트와 결합 객체의리스트를 검색한다.
사람의 알고는 나도 LINQ를 사용하거나이 정확한 문자열을 사용하여 C #에서 이것을 사용할 수 있는가하는 방법?
나는 그들이 더 이상 사용되지 않습니다 것 같아요 - 나는 다음과 같은 코드를 사용하여 시도하지만 QueryDocument 및 MongoCursor의 유형을 찾을 수 없습니다?
BsonDocument document = MongoDB.Bson.Serialization.BsonSerializer.Deserialize<BsonDocument>("{ name : value }");
QueryDocument queryDoc = new QueryDocument(document);
MongoCursor toReturn = _connectionCollection.Find(queryDoc);
해결법
-
==============================
1.JSON을 구문 분석 할 필요가 없습니다. 여기에 모든 것이 실제로 LINQ 또는 집계 유창함 인터페이스 중 하나를 직접 수행 할 수 있습니다.
JSON을 구문 분석 할 필요가 없습니다. 여기에 모든 것이 실제로 LINQ 또는 집계 유창함 인터페이스 중 하나를 직접 수행 할 수 있습니다.
문제는 정말 갈 훨씬 제공하지 않기 때문에 그냥 몇 가지 데모 클래스를 사용하여.
기본적으로 우리가되고, 여기에 두 개의 컬렉션이
엔티티
{ "_id" : ObjectId("5b08ceb40a8a7614c70a5710"), "name" : "A" } { "_id" : ObjectId("5b08ceb40a8a7614c70a5711"), "name" : "B" }
다른 사람
{ "_id" : ObjectId("5b08cef10a8a7614c70a5712"), "entity" : ObjectId("5b08ceb40a8a7614c70a5710"), "name" : "Sub-A" } { "_id" : ObjectId("5b08cefd0a8a7614c70a5713"), "entity" : ObjectId("5b08ceb40a8a7614c70a5711"), "name" : "Sub-B" }
그리고 클래스의 몇 그들을 그냥 아주 기본적인 예제에 바인딩 :
public class Entity { public ObjectId id; public string name { get; set; } } public class Other { public ObjectId id; public ObjectId entity { get; set; } public string name { get; set; } } public class EntityWithOthers { public ObjectId id; public string name { get; set; } public IEnumerable<Other> others; } public class EntityWithOther { public ObjectId id; public string name { get; set; } public Other others; }
var listNames = new[] { "A", "B" }; var query = entities.Aggregate() .Match(p => listNames.Contains(p.name)) .Lookup( foreignCollection: others, localField: e => e.id, foreignField: f => f.entity, @as: (EntityWithOthers eo) => eo.others ) .Project(p => new { p.id, p.name, other = p.others.First() } ) .Sort(new BsonDocument("other.name",-1)) .ToList();
요청이 서버로 전송 :
[ { "$match" : { "name" : { "$in" : [ "A", "B" ] } } }, { "$lookup" : { "from" : "others", "localField" : "_id", "foreignField" : "entity", "as" : "others" } }, { "$project" : { "id" : "$_id", "name" : "$name", "other" : { "$arrayElemAt" : [ "$others", 0 ] }, "_id" : 0 } }, { "$sort" : { "other.name" : -1 } } ]
유창 인터페이스는 기본적으로 일반 BSON 구조와 동일하기 때문에 아마도 가장 쉬운 이해합니다. $ 조회 단계 모두를 동일한 인수를 보유하고 $ arrayElemAt을 처음에 표시된다 (). $의 경우 종류 당신은 단순히 BSON 문서 또는 다른 유효한 식을 제공 할 수 있습니다.
또 다른 위 MongoDB를 3.6과의 하위 파이프 라인 문 $ 조회의 새로운 표현 형태이다.
BsonArray subpipeline = new BsonArray(); subpipeline.Add( new BsonDocument("$match",new BsonDocument( "$expr", new BsonDocument( "$eq", new BsonArray { "$$entity", "$entity" } ) )) ); var lookup = new BsonDocument("$lookup", new BsonDocument("from", "others") .Add("let", new BsonDocument("entity", "$_id")) .Add("pipeline", subpipeline) .Add("as","others") ); var query = entities.Aggregate() .Match(p => listNames.Contains(p.name)) .AppendStage<EntityWithOthers>(lookup) .Unwind<EntityWithOthers, EntityWithOther>(p => p.others) .SortByDescending(p => p.others.name) .ToList();
요청이 서버로 전송 :
[ { "$match" : { "name" : { "$in" : [ "A", "B" ] } } }, { "$lookup" : { "from" : "others", "let" : { "entity" : "$_id" }, "pipeline" : [ { "$match" : { "$expr" : { "$eq" : [ "$$entity", "$entity" ] } } } ], "as" : "others" } }, { "$unwind" : "$others" }, { "$sort" : { "others.name" : -1 } } ]
유창 "빌더"직접 아직 구문을 지원하거나하지 않습니다 LINQ 표현하지만 여전히 BsonDocument 및 BsonArray 또는 다른 유효한 표현식을 사용하여 구성 할 수있다,는 $ EXPR 연산자를 지원합니다. 여기에서 우리는 또한 일종의 표현보다는 이전 같이 BsonDocument를 사용하여 $을 적용하기 위해 $ 언 와인드 결과를 "입력".
이외에도 다른 용도로부터 "하위 파이프 라인 '의 주요 임무는 $ 조회의 대상 배열에 반환 된 문서를 줄이는 것입니다. 이것은 일반적으로 단지 결과 배열의 첫 번째 요소를 잡는 것보다 더 효율적 그래서 또한 언 와인드 여기에 $ 실제로 서버 실행에 $ 조회 문에 "통합"되는 목적을 제공합니다.
var query = entities.AsQueryable() .Where(p => listNames.Contains(p.name)) .GroupJoin( others.AsQueryable(), p => p.id, o => o.entity, (p, o) => new { p.id, p.name, other = o.First() } ) .OrderByDescending(p => p.other.name);
요청이 서버로 전송 :
[ { "$match" : { "name" : { "$in" : [ "A", "B" ] } } }, { "$lookup" : { "from" : "others", "localField" : "_id", "foreignField" : "entity", "as" : "o" } }, { "$project" : { "id" : "$_id", "name" : "$name", "other" : { "$arrayElemAt" : [ "$o", 0 ] }, "_id" : 0 } }, { "$sort" : { "other.name" : -1 } } ]
이것은 거의 동일하지만, 단지 다른 인터페이스를 사용하고 약간 다른 BSON 문을 생성하고, 정말 때문 만이 기능 문에서 단순화 된 이름의. 이것은 단순히) (A SelectMany에서 생산 된 같은 $의 풀림을 사용하는 다른 가능성을 가지고 않습니다 :
var query = entities.AsQueryable() .Where(p => listNames.Contains(p.name)) .GroupJoin( others.AsQueryable(), p => p.id, o => o.entity, (p, o) => new { p.id, p.name, other = o } ) .SelectMany(p => p.other, (p, other) => new { p.id, p.name, other }) .OrderByDescending(p => p.other.name);
요청이 서버로 전송 :
[ { "$match" : { "name" : { "$in" : [ "A", "B" ] } } }, { "$lookup" : { "from" : "others", "localField" : "_id", "foreignField" : "entity", "as" : "o" }}, { "$project" : { "id" : "$_id", "name" : "$name", "other" : "$o", "_id" : 0 } }, { "$unwind" : "$other" }, { "$project" : { "id" : "$id", "name" : "$name", "other" : "$other", "_id" : 0 }}, { "$sort" : { "other.name" : -1 } } ]
일반적으로 직접 $ 조회 다음 언 와인드 $를 배치하는 것은 실제로 통합 프레임 워크에 대한 "최적의 패턴"입니다. 그러나 .NET 드라이버는 혼란을 사이에 $ 프로젝트를 강요하기보다는 "등"에 대한 묵시적 이름을 사용하여이 조합이 최대 않습니다. 하지 그에 대한 경우 당신은 당신이 "하나"관련 결과를 알고있을 때,이 사실은 더 $의 arrayElemAt보다. 당신이 "합체"언 와인드 $을 원하는 경우에, 당신은 더 유창 인터페이스, 이상을 보여 같은 다른 양식을 사용하여 꺼져 있습니다.
var query = from p in entities.AsQueryable() where listNames.Contains(p.name) join o in others.AsQueryable() on p.id equals o.entity into joined select new { p.id, p.name, other = joined.First() } into p orderby p.other.name descending select p;
요청이 서버로 전송 :
[ { "$match" : { "name" : { "$in" : [ "A", "B" ] } } }, { "$lookup" : { "from" : "others", "localField" : "_id", "foreignField" : "entity", "as" : "joined" } }, { "$project" : { "id" : "$_id", "name" : "$name", "other" : { "$arrayElemAt" : [ "$joined", 0 ] }, "_id" : 0 } }, { "$sort" : { "other.name" : -1 } } ]
모든 꽤 친숙하고 정말 그냥 아래로 기능 명명합니다. 그냥 $ 언 와인드 옵션을 사용하여와 같은 :
var query = from p in entities.AsQueryable() where listNames.Contains(p.name) join o in others.AsQueryable() on p.id equals o.entity into joined from sub_o in joined.DefaultIfEmpty() select new { p.id, p.name, other = sub_o } into p orderby p.other.name descending select p;
요청이 서버로 전송 :
[ { "$match" : { "name" : { "$in" : [ "A", "B" ] } } }, { "$lookup" : { "from" : "others", "localField" : "_id", "foreignField" : "entity", "as" : "joined" } }, { "$unwind" : { "path" : "$joined", "preserveNullAndEmptyArrays" : true } }, { "$project" : { "id" : "$_id", "name" : "$name", "other" : "$joined", "_id" : 0 } }, { "$sort" : { "other.name" : -1 } } ]
실제로 "최적화 합체"양식을 사용하고있다. 번역자는 여전히 우리가 문을 유효하게하기 위해 중간 선택을 필요로하기 때문에 $ 프로젝트를 추가하는 주장한다.
그래서 본질적으로 정확히 같은 결과를 같은 쿼리 문 기본적으로 무엇인지에 도착하기 위해 꽤 몇 가지 방법이 있습니다. 당신이 BsonDocument 양식으로 JSON을 구문 분석하고 유창 집계 () 명령이 먹이를 "수"동안, 그들이 쉽게 같은 문에지도 않는 자연 빌더 또는 LINQ 인터페이스를 사용하는 것이 일반적으로 좋습니다.
$ 해제하는 옵션은 크게 표시되기 때문에 심지어 "합체"형태는 실제로 훨씬 더 최적의 후 "첫 번째"배열 요소를 취할 $ arrayElemAt을 사용하고있는 "단수"일치와. $ 조회 대상 배열이 부모 문서가 더 필터링없이 16메가바이트을 초과 할 수있는 곳도 BSON 제한 같은 것들의 고려 사항 더 중요합니다. 일치하는 파이프 라인에서 문서의 집계 $ 조회 총 크기에 여기에 또 다른 게시물이 실제로에만이 시간에 능통 인터페이스에 사용할 수 등의 옵션 또는 기타 조회 () 구문을 사용하여 박히는 그 한계를 방지하는 방법에 대해 설명 최대 문서 크기를 초과 .
-
==============================
2.여기 MongoDB.Entities 함께 할 방법은 다음과 같습니다. 두 기관 중 하나 일대 다 또는 다 대다 관계에있는 경우에, 당신은 다음과 같이 수동으로 조인 할 필요없이 역의 관계에 액세스 할 수 있습니다. [면책 조항 : 나는 라이브러리의 저자 해요]
여기 MongoDB.Entities 함께 할 방법은 다음과 같습니다. 두 기관 중 하나 일대 다 또는 다 대다 관계에있는 경우에, 당신은 다음과 같이 수동으로 조인 할 필요없이 역의 관계에 액세스 할 수 있습니다. [면책 조항 : 나는 라이브러리의 저자 해요]
using System; using System.Linq; using MongoDB.Entities; using MongoDB.Driver.Linq; namespace StackOverflow { public class Program { public class Author : Entity { public string Name { get; set; } public Many<Book> Books { get; set; } public Author() => this.InitOneToMany(() => Books); } public class Book : Entity { public string Title { get; set; } } static void Main(string[] args) { new DB("test"); var book = new Book { Title = "The Power Of Now" }; book.Save(); var author = new Author { Name = "Eckhart Tolle" }; author.Save(); author.Books.Add(book); //build a query for finding all books that has Power in the title. var bookQuery = DB.Queryable<Book>() .Where(b => b.Title.Contains("Power")); //find all the authors of books that has a title with Power in them var authors = author.Books .ParentsQueryable<Author>(bookQuery); //also can pass in an ID or array of IDs //get the result var result = authors.ToArray(); //output the aggregation pipeline Console.WriteLine(authors.ToString()); Console.ReadKey(); } } }
from https://stackoverflow.com/questions/50530363/aggregate-lookup-with-c-sharp by cc-by-sa and MIT license
'MONGODB' 카테고리의 다른 글
[MONGODB] 정렬 된 페이징 주어진 레코드에 대한 값을 생략 계산 (0) | 2019.12.08 |
---|---|
[MONGODB] upsert와 키 오류를 중복 몽구스 (0) | 2019.12.08 |
[MONGODB] MongoDB의 진수 형식을 사용하는 방법 (0) | 2019.12.08 |
[MONGODB] 몽구스 발견 () 반환하지 결과 (0) | 2019.12.08 |
[MONGODB] MongoDB의에서 중복 제거 (0) | 2019.12.08 |