LINQ
개요
이 가이드에서는 MongoDB .NET/C# 드라이버와 함께 LINQ를 사용하는 방법을 배울 수 있습니다. LINQ를 사용하면 언어 키워드 및 연산자를 사용하여 강력한 형식의 객체 컬렉션에 대한 쿼리를 생성할 수 있습니다. .NET/C# 드라이버는 자동으로 LINQ 쿼리를 집계 작업으로 변환합니다.
이 가이드의 예시에서는 Atlas 샘플 데이터 세트에 제공된 sample_restaurants
데이터베이스의 restaurants
컬렉션을 사용합니다. 무료 MongoDB Atlas 클러스터를 생성하고 샘플 데이터 세트를 로드하는 방법에 대한 자세한 내용은 빠른 시작을 참조하세요.
다음 Restaurant
, Address
및 GradeEntry
클래스는 이 컬렉션의 문서를 모델링합니다.
public class Restaurant { public ObjectId Id { get; set; } public string Name { get; set; } [ ] public string RestaurantId { get; set; } public string Cuisine { get; set; } public Address Address { get; set; } public string Borough { get; set; } public List<GradeEntry> Grades { get; set; } }
public class Address { public string Building { get; set; } [ ] public float[] Coordinates { get; set; } public string Street { get; set; } [ ] public string ZipCode { get; set; } }
public class GradeEntry { public DateTime Date { get; set; } public string Grade { get; set; } public float Score { get; set; } }
참고
restaurants
컬렉션의 문서는 카멜 케이스 명명 규칙을 사용합니다. 이 가이드의 예시에서는 ConventionPack
사용하여 컬렉션의 필드를 파스칼식 대/소문자로 역직렬화하고 Restaurant
클래스의 속성에 매핑합니다.
사용자 지정 직렬화에 대해 자세히 알아보려면 사용자 지정 직렬화를참조하세요.
컬렉션을 쿼리 가능하게 만들기
LINQ를 사용하여 컬렉션을 쿼리하려면 먼저 컬렉션에 연결되는 IQueryable 객체를 만들어야 합니다. 객체를 만들려면 다음과 같이 AsQueryable()
메서드를 사용합니다.
var restaurantsCollection = restaurantsDatabase.GetCollection<Restaurant>("restaurants"); var queryableCollection = restaurantsCollection.AsQueryable();
AsQueryable()
메서드가 MongoDB 특정 메서드 세트와 함께 IQueryable
확장자 메서드를 포함하는 IMongoQueryable 인스턴스를 반환합니다.
쿼리 가능한 객체가 있으면 메서드 구문을 사용하여 쿼리를 작성할 수 있습니다. 일부 파이프라인 단계는 SQL 쿼리 구문과 유사한 쿼리 이해 구문도 지원합니다.
Method Syntax 또는 Query Syntax 탭을 선택하면 LINQ를 사용하여 쿼리를 작성하는 방법을 볼 수 있습니다.
var query = queryableCollection .Where(r => r.Name == "The Movable Feast") .Select(r => new { r.Name, r.Address });
var query = from r in queryableCollection where r.Name == "The Movable Feast" select new { r.Name, r.Address };
이전 예시의 결과를 다음과 같이 출력할 수 있습니다.
foreach (var restaurant in query) { Console.WriteLine(restaurant.ToJson()); }
{ "name" : "The Movable Feast", "address" : { "building" : "284", "coord" : [-73.982923900000003, 40.6580753], "street" : "Prospect Park West", "zipcode" : "11215" } }
팁
쿼리 결과 액세스
ToList()
또는 ToCursor()
메서드를 사용하여 쿼리 결과에 액세스할 수도 있습니다:
var results = query.ToList();
var results = query.ToCursor();
지원되는 집계 단계
LINQ를 사용하여 집계 파이프라인을 생성할 수 있습니다. .NET/C# 드라이버는 각 LINQ 구문을 해당 집계 파이프라인 단계로 자동 변환합니다. 이 섹션에서는 어떤 집계 파이프라인 단계가 지원되는지 알아볼 수 있습니다.
집계 파이프라인 단계에 대해 자세히 알아보려면 서버 매뉴얼의 집계 단계 페이지를 참조하세요.
프로젝트
$project
집계 단계에서는 지정된 필드만 포함된 문서를 반환합니다.
Method Syntax 또는 Query Syntax 탭을 선택하여 LINQ를 사용하여 $project
단계를 생성하는 방법을 확인합니다:
var query = queryableCollection .Select(r => new { r.Name, r.Address });
var query = from r in queryableCollection select new { r.Name, r.Address };
이전 예시의 결과에는 다음 문서가 포함됩니다.
{ "name" : "The Movable Feast", "address" : { "building" : "284", "coord" : [-73.982923900000003, 40.6580753], "street" : "Prospect Park West", "zipcode" : "11215" } }
참고
_id 필드 제외
LINQ 프로젝션에 _id
필드를 포함하지 않은 경우 .NET/C# 드라이버가 결과에서 자동으로 제외합니다.
$매치
$match
집계 단계에서는 지정된 기준과 일치하는 문서를 반환합니다.
Method Syntax 또는 Query Syntax 탭을 선택하여 LINQ를 사용하여 $match
단계를 생성하는 방법을 확인합니다:
var query = queryableCollection .Where(r => r.Name == "The Movable Feast");
var query = from r in queryableCollection where r.Name == "The Movable Feast" select r;
이전 예시의 결과에는 다음 문서가 포함됩니다.
// Results Truncated { "_id" : ObjectId(...), "name" : "The Movable Feast", "restaurant_id" : "40361606", "cuisine" : "American", "address" : {...}, "borough" : "Brooklyn", "grades" : [...] }
$limit
$limit
집계 단계는 쿼리에서 반환되는 문서 수를 제한합니다. 다음 예는 LINQ를 사용하여 $limit
스테이지를 생성하는 방법을 보여 줍니다:
var query = queryableCollection .Where(r => r.Cuisine == "Italian") .Select(r => new {r.Name, r.Cuisine}) .Take(5);
이전 예시의 결과에는 다음 문서가 포함됩니다.
{ "name" : "Philadelhia Grille Express", "cuisine" : "Italian" } { "name" : "Isle Of Capri Resturant", "cuisine" : "Italian" } { "name" : "Marchis Restaurant", "cuisine" : "Italian" } { "name" : "Crystal Room", "cuisine" : "Italian" } { "name" : "Forlinis Restaurant", "cuisine" : "Italian" }
$skip
$skip
집계 단계에서는 쿼리에서 반환한 지정된 수의 문서를 건너뛰고 나머지 결과를 반환합니다. 다음 예는 LINQ를 사용하여 $skip
단계를 생성하는 방법을 보여 줍니다:
var query = queryableCollection .Where(r => r.Cuisine == "Italian") .Select(r => new {r.Name, r.Cuisine}) .Skip(2);
앞의 예에서는 기준과 일치하는 처음 두 레스토랑을 건너뛰고 나머지를 반환합니다. 결과에는 다음 문서가 포함됩니다:
// Results Truncated { "name" : "Marchis Restaurant", "cuisine" : "Italian" } { "name" : "Crystal Room", "cuisine" : "Italian" } { "name" : "Forlinis Restaurant", "cuisine" : "Italian" } ...
$unwind
$unwind
집계 단계는 지정된 배열 필드를 분해하고 해당 배열의 각 요소에 대한 문서를 반환합니다.
Method Syntax 또는 Query Syntax 탭을 선택하면 LINQ를 사용하여 $unwind
단계를 생성하는 방법을 볼 수 있습니다.
var query = queryableCollection .Where(r => r.Name == "The Movable Feast") .SelectMany(r => r.Grades);
var query = from r in queryableCollection where r.Name == "The Movable Feast" from grade in r.Grades select grade;
위 예의 쿼리는 Name
필드의 값이 "The Movable Feast"인 문서를 찾습니다. 그런 다음 이 문서의 Grades
배열에 있는 각 요소에 대해 쿼리는 새 문서를 반환합니다. 결과에는 다음 문서가 포함됩니다.
{ "date" : ISODate("2014-11-19T00:00:00Z"), "grade" : "A", "score" : 11 } { "date" : ISODate("2013-11-14T00:00:00Z"), "grade" : "A", "score" : 2 } { "date" : ISODate("2012-12-05T00:00:00Z"), "grade" : "A", "score" : 13 } { "date" : ISODate("2012-05-17T00:00:00Z"), "grade" : "A", "score" : 11 }
$그룹
$group
집계 단계에서는 지정한 기준에 따라 문서를 그룹으로 분리합니다.
Method Syntax 또는 Query Syntax 탭을 선택하면 LINQ를 사용하여 $group
단계를 생성하는 방법을 볼 수 있습니다.
var query = queryableCollection .GroupBy(r => r.Cuisine) .Select(g => new { Cuisine = g.Key, Count = g.Count() });
var query = from r in queryableCollection group r by r.Cuisine into g select new {Cuisine = g.Key, Count = g.Count()};
앞의 예시에서는 각 문서를 Cuisine
필드의 값으로 그룹화한 다음 각 Cuisine
값이 있는 문서 수를 계산합니다. 결과에는 다음 문서가 포함됩니다.
// Results Truncated { "cuisine" : "Caribbean", "count" : 657 } { "cuisine" : "Café/Coffee/Tea", "count" : 1214 } { "cuisine" : "Iranian", "count" : 2 } { "cuisine" : "Nuts/Confectionary", "count" : 6 } { "cuisine" : "Middle Eastern", "count" : 168 } ...
참고
결과 순서
앞의 쿼리가 항상 동일한 순서로 결과를 반환하는 것은 아닙니다. 이 예시를 실행하면 위에 표시된 것과 다른 순서로 결과가 반환될 수 있습니다.
$sort
$sort
집계 단계는 지정한 순서대로 쿼리 결과를 반환합니다.
Method Syntax 또는 Query Syntax 탭을 선택하면 LINQ를 사용하여 $sort
단계를 생성하는 방법을 볼 수 있습니다.
var query = queryableCollection .OrderBy(r => r.Name) .ThenByDescending(r => r.RestaurantId);
var query = from r in queryableCollection orderby r.Name, r.RestaurantId descending select r;
위 예시에서는 Name
필드를 기준으로 알파벳순으로 정렬된 쿼리 결과를 반환하고, 2차적으로 RestaurantId
필드에서는 내림차순으로 정렬합니다. 다음은 반환된 결과에 포함된 문서의 하위 집합입니다.
// Results Truncated ... { "_id" : ObjectId(...), "name" : "Aba Turkish Restaurant", "restaurant_id" : "41548686", "cuisine" : "Turkish", "address" : {...}, "borough" : "Manhattan", "grades" : [...] } { "_id" : ObjectId(...), "name" : "Abace Sushi", "restaurant_id" : "50006214", "cuisine" : "Japanese", "address" : { ... }, "borough" : "Manhattan", "grades" : [...] } { "_id" : ObjectId(...), "name" : "Abacky Potluck", "restaurant_id" : "50011222", "cuisine" : "Asian", "address" : { ... }, "borough" : "Manhattan", "grades" : [...] } { "_id" : ObjectId(...), "name" : "Abaleh", "restaurant_id" : "50009096", "cuisine" : "Mediterranean", "address" : { ... }, "borough" : "Manhattan", "grades" : [...] } ...
$lookup
$lookup
집계 단계는 한 컬렉션의 문서를 동일한 데이터베이스의 다른 컬렉션에 있는 문서와 조인합니다. $lookup
단계에서는 각 입력 문서에 새 배열 필드를 추가합니다. 새 배열 필드에는 '조인'된 컬렉션에서
일치하는 문서들이 포함됩니다.
참고
조회를 수행하려면 AsQueryable
메서드를 사용하여 두 컬렉션을 모두 쿼리할 수 있도록 설정해야 합니다.
컬렉션을 쿼리 가능하게 만드는 방법을 알아보려면 컬렉션을 쿼리 가능하게 만들기를 참조하세요.
레스토랑 리뷰가 있는 reviews
라는 sample_restaurants
데이터베이스의 두 번째 컬렉션을 생각해 보세요. $lookup
단계를 사용하여 해당 컬렉션의 문서를 restaurants
컬렉션의 동일한 name
값을 가진 문서에 조인할 수 있습니다.
다음 Review
클래스는 reviews
컬렉션의 문서를 모델링합니다.
public class Review { public ObjectId Id { get; set; } [ ] public string RestaurantName { get; set; } public string Reviewer { get; set; } [ ] public string ReviewText { get; set; } }
Method Syntax 또는 Query Syntax 탭을 선택하여 LINQ를 사용하여 $lookup
단계를 생성하는 방법을 확인합니다:
var query = queryableCollection .GroupJoin(reviewCollection, restaurant => restaurant.Name, review => review.RestaurantName, (restaurant, reviews) => new { Restaurant = restaurant, Reviews = reviews } );
var query = from restaurant in queryableCollection join rv in reviewCollection on restaurant.Name equals rv.RestaurantName into reviews select new { restaurant, reviews };
앞의 예에서는 restaurants
컬렉션의 모든 문서를 반환합니다. 각 레스토랑 문서에는 해당 레스토랑에 대한 모든 리뷰가 포함된 reviews
추가 필드가 있습니다. 리뷰 문서의 name
필드 값이 레스토랑 문서의 name
필드 값과 일치하면 리뷰가 레스토랑과 일치합니다.
다음은 반환된 결과의 하위 집합입니다:
// Results Truncated { "restaurant" : { "_id" : ObjectId("..."), "name" : "The Movable Feast", "restaurant_id" : "40361606", "cuisine" : "American", "address" : {...}, "borough" : "Brooklyn", "grades" : [...] }, "reviews" : [ { "_id" : ObjectId(...), "restaurant_name" : "The Movable Feast", "reviewer" : "Lazlo Cravensworth", "review_text" : "Great restaurant! 12/10 stars!" }, { "_id" : ObjectId("..."), "restaurant_name" : "The Movable Feast", "reviewer" : "Michael Scarn", "review_text" : "It really was a feast" } ] }
지원되지 않는 집계 단계
LINQ의 MongoDB .NET/C# 드라이버 구현은 다음 집계 단계를 지원하지 않습니다.
$redact
$geoNear
$out
지원되는 방법
다음은 LINQ의 MongoDB .NET/C# 드라이버 구현에서 지원되는 몇 가지 메서드입니다.
메서드 이름 | 설명 |
---|---|
Any | 지정된 기준과 일치하는 문서가 있는지 확인합니다. |
Average | 지정된 필드의 평균을 계산합니다. |
Count | 지정된 기준과 일치하는 문서 수를 나타내는 Int32 를 반환합니다. |
LongCount | 지정된 기준과 일치하는 문서 수를 나타내는 Int64 를 반환합니다. |
Distinct | 지정된 조건과 일치하는 고유한 문서를 반환합니다. |
First | 일치하는 첫 번째 문서를 반환하고, 일치하는 문서가 없으면 예외를 발생시킵니다. |
FirstOrDefault | 일치하는 첫 번째 문서를 반환하거나 일치하는 문서가 없는 경우 null 을 반환합니다. |
GroupBy | 지정된 기준에 따라 문서 그룹화 |
GroupJoin | 동일한 데이터베이스의 다른 컬렉션에 대한 왼쪽 외부 조인을 수행합니다. |
Max | 지정된 최대값을 가진 문서 반환 |
OfType | 지정된 유형과 일치하는 문서 반환 |
OrderBy , OrderByDescending | 지정된 정렬 순서로 결과 반환 |
ThenBy , ThenByDescending | 세컨더리 정렬을 지정할 수 있습니다. |
Select | 지정된 기준에 따라 문서를 선택합니다. |
SelectMany | 시퀀스의 각 요소를 프로젝션하고 결과 시퀀스를 하나의 문서로 결합 |
Single | 일치하는 문서 하나만 반환하고 문서의 개수가 하나가 아닐 경우 예외 발생 |
SingleOrDefault | 일치하는 단일 문서를 반환하고, 일치하는 문서가 없으면 null 을 반환 |
Skip | 지정된 수의 문서를 건너뛰고 나머지 결과를 반환합니다. |
Sum | 지정된 필드에 있는 값의 합계 반환 |
Take | 반환할 결과의 수 지정 |
Where | 지정한 기준과 일치하는 모든 문서 반환 |