Skip to content

Commit 0fdae59

Browse files
committed
DOCSP-45007: Distinct
1 parent 051e6ca commit 0fdae59

File tree

3 files changed

+359
-0
lines changed

3 files changed

+359
-0
lines changed

source/fundamentals/crud/read-operations.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ Read Operations
1212

1313
Retrieve Data </fundamentals/crud/read-operations/retrieve>
1414
Count Documents </fundamentals/crud/read-operations/count>
15+
/fundamentals/crud/read-operations/distinct
1516
Monitor Data Changes </fundamentals/crud/read-operations/change-streams>
1617

1718
- :ref:`csharp-retrieve`
1819
- :ref:`csharp-count-documents`
20+
- :ref:`csharp-distinct`
1921
- :ref:`csharp-change-streams`
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
.. _csharp-distinct:
2+
3+
==============================
4+
Retrieve Distinct Field Values
5+
==============================
6+
7+
.. contents:: On this page
8+
:local:
9+
:backlinks: none
10+
:depth: 2
11+
:class: singlecol
12+
13+
.. facet::
14+
:name: genre
15+
:values: reference
16+
17+
.. meta::
18+
:keywords: read, unique, code example
19+
20+
Overview
21+
--------
22+
23+
In this guide, you can learn how to use the {+driver-short+} to retrieve the
24+
distinct values of a specified field across a collection.
25+
26+
Within a collection, different documents might contain different values for a
27+
single field. For example, one document in a ``restaurants`` collection has a
28+
``borough`` value of ``"Manhattan"``, and another has a ``borough`` value of
29+
``"Queens"``. By using the {+driver-short+}, you can retrieve all the unique values
30+
that a field contains across multiple documents in a collection.
31+
32+
Sample Data
33+
~~~~~~~~~~~
34+
35+
The examples in this guide use the ``sample_restaurants.restaurants`` collection
36+
from the :atlas:`Atlas sample datasets </sample-data>`. To learn how to create a
37+
free MongoDB Atlas cluster and load the sample datasets, see the :ref:`<csharp-quickstart>`.
38+
39+
Retrieve Distinct Values
40+
------------------------
41+
42+
To retrieve the distinct values for a specified field, call the ``IMongoCollection<TDocument>.Distinct()``
43+
or ``IMongoCollection<TDocument>.DistinctAsync()`` method and pass the name of the field
44+
you want to find distinct values for.
45+
46+
Retrieve Values Across a Collection
47+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
48+
49+
The following example retrieves the distinct values of the ``borough`` field in
50+
the ``restaurants`` collection. Select the :guilabel:`Asynchronous` or :guilabel:`Synchronous`
51+
tab to see the corresponding code.
52+
53+
54+
.. tabs::
55+
56+
.. tab:: Asynchronous
57+
:tabid: distinct-async
58+
59+
.. io-code-block::
60+
:copyable:
61+
62+
.. input:: /includes/fundamentals/code-examples/Distinct.cs
63+
:start-after: start-distinct-async
64+
:end-before: end-distinct-async
65+
:language: csharp
66+
:dedent:
67+
68+
.. output::
69+
:visible: false
70+
71+
Bronx
72+
Brooklyn
73+
Manhattan
74+
Missing
75+
Queens
76+
Staten Island
77+
78+
.. tab:: Synchronous
79+
:tabid: distinct-sync
80+
81+
.. io-code-block::
82+
:copyable:
83+
84+
.. input:: /includes/fundamentals/code-examples/Distinct.cs
85+
:start-after: start-distinct
86+
:end-before: end-distinct
87+
:language: csharp
88+
:dedent:
89+
90+
.. output::
91+
:visible: false
92+
93+
Bronx
94+
Brooklyn
95+
Manhattan
96+
Missing
97+
Queens
98+
Staten Island
99+
100+
The operation returns a cursor that you can iterate through to access each distinct ``borough``
101+
field value. Although several documents have the same value in the ``borough`` field, each value appears
102+
in the results only once.
103+
104+
Retrieve Values Across Specified Documents
105+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
106+
107+
You can provide a **query filter** to the ``Distinct()`` and ``DistinctAsync()`` methods
108+
to find distinct field values within a subset of documents in a collection. A query filter
109+
is an expression that specifies search criteria used to match documents in an operation.
110+
For more information about creating a query filter, see the :ref:`csharp-specify-query` guide.
111+
112+
The following example retrieves the distinct values of the ``borough`` field for
113+
all documents that have a ``cuisine`` field value of ``"Italian"``. Select the
114+
:guilabel:`Asynchronous` or :guilabel:`Synchronous` tab to see the corresponding code.
115+
116+
.. tabs::
117+
118+
.. tab:: Asynchronous
119+
:tabid: distinct-async
120+
121+
.. io-code-block::
122+
:copyable:
123+
124+
.. input:: /includes/fundamentals/code-examples/Distinct.cs
125+
:start-after: start-distinct-with-query-async
126+
:end-before: end-distinct-with-query-async
127+
:language: csharp
128+
:dedent:
129+
130+
.. output::
131+
:visible: false
132+
133+
Bronx
134+
Brooklyn
135+
Manhattan
136+
Queens
137+
Staten Island
138+
139+
.. tab:: Synchronous
140+
:tabid: distinct-sync
141+
142+
.. io-code-block::
143+
:copyable:
144+
145+
.. input:: /includes/fundamentals/code-examples/Distinct.cs
146+
:start-after: start-distinct-with-query
147+
:end-before: end-distinct-with-query
148+
:language: csharp
149+
:dedent:
150+
151+
.. output::
152+
:visible: false
153+
154+
Bronx
155+
Brooklyn
156+
Manhattan
157+
Queens
158+
Staten Island
159+
160+
Modify Distinct Behavior
161+
~~~~~~~~~~~~~~~~~~~~~~~~
162+
163+
You can modify the behavior of the ``Distinct()`` and ``DistinctAsync()`` methods by
164+
providing a ``DistinctOptions`` instance as an optional parameter. The following table
165+
describes the properties you can set on a ``DistinctOptions`` instance:
166+
167+
.. list-table::
168+
:widths: 30 70
169+
:header-rows: 1
170+
171+
* - Method
172+
- Description
173+
174+
* - ``Collation``
175+
- | Sets the collation to use for the operation.
176+
| **Parameter Type**: ``Collation``
177+
178+
* - ``MaxTime``
179+
- | Sets the maximum amount of time that the operation can run.
180+
| **Parameter Type**: ``TimeSpan``
181+
182+
* - ``Comment``
183+
- | Attaches a comment to the operation.
184+
| **Parameter Type**: ``BsonValue`` or ``String``
185+
186+
The following example retrieves the distinct values of the ``name`` field for
187+
all documents that have a ``borough`` field value of ``"Bronx"`` and a
188+
``cuisine`` field value of ``"Pizza"``. Then, it adds a comment to the operation by
189+
providing a ``DistinctOptions`` instance to the ``Distinct()`` method.
190+
191+
Select the :guilabel:`Asynchronous` or :guilabel:`Synchronous` tab to see the
192+
corresponding code.
193+
194+
.. tabs::
195+
196+
.. tab:: Asynchronous
197+
:tabid: distinct-async
198+
199+
.. io-code-block::
200+
:copyable:
201+
202+
.. input:: /includes/fundamentals/code-examples/Distinct.cs
203+
:start-after: start-distinct-with-comment-async
204+
:end-before: end-distinct-with-comment-async
205+
:language: csharp
206+
:dedent:
207+
208+
.. output::
209+
:visible: false
210+
211+
$1.25 Pizza
212+
18 East Gunhill Pizza
213+
2 Bros
214+
Aenos Pizza
215+
Alitalia Pizza Restaurant
216+
Amici Pizza And Pasta
217+
Angie'S Cafe Pizza
218+
...
219+
220+
.. tab:: Synchronous
221+
:tabid: distinct-sync
222+
223+
.. io-code-block::
224+
:copyable:
225+
226+
.. input:: /includes/fundamentals/code-examples/Distinct.cs
227+
:start-after: start-distinct-with-comment
228+
:end-before: end-distinct-with-comment
229+
:language: csharp
230+
:dedent:
231+
232+
.. output::
233+
:visible: false
234+
235+
$1.25 Pizza
236+
18 East Gunhill Pizza
237+
2 Bros
238+
Aenos Pizza
239+
Alitalia Pizza Restaurant
240+
Amici Pizza And Pasta
241+
Angie'S Cafe Pizza
242+
...
243+
244+
API Documentation
245+
-----------------
246+
247+
To learn more about any of the methods or types discussed in this
248+
guide, see the following API documentation:
249+
250+
- `Distinct() <{+new-api-root+}/MongoDB.Driver/MongoDB.Driver.IMongoCollection-1.Distinct.html>`__
251+
- `DistinctAsync() <{+new-api-root+}/MongoDB.Driver/MongoDB.Driver.IMongoCollection-1.DistinctAsync.html>`__
252+
- `DistinctOptions <{+new-api-root+}/MongoDB.Driver/MongoDB.Driver.DistinctOptions.html>`__
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
using MongoDB.Bson;
2+
using MongoDB.Bson.Serialization.Attributes;
3+
using MongoDB.Bson.Serialization.Conventions;
4+
using MongoDB.Driver;
5+
6+
public class LimitSortSkip
7+
{
8+
// Replace with your connection string
9+
private const string MongoConnectionString = "<connection string URI>>";
10+
11+
public static void Main(string[] args)
12+
{
13+
var mongoClient = new MongoClient(MongoConnectionString);
14+
var database = mongoClient.GetDatabase("sample_restaurants");
15+
var collection = database.GetCollection<Restaurant>("restaurants");
16+
17+
{
18+
// start-distinct
19+
var results = collection.Distinct<string>("borough", new BsonDocument()).ToList();
20+
foreach (var result in results)
21+
{
22+
Console.WriteLine(result);
23+
}
24+
// end-distinct
25+
}
26+
27+
{
28+
// start-distinct-with-query
29+
var filter = Builders<Restaurant>.Filter.Eq("cuisine", "Italian");
30+
var results = collection.Distinct<string>("borough", filter).ToList();
31+
foreach (var result in results)
32+
{
33+
Console.WriteLine(result);
34+
}
35+
// end-distinct-with-query
36+
}
37+
38+
{
39+
// start-distinct-with-comment
40+
var cuisineFilter = Builders<Restaurant>.Filter.Eq("cuisine", "Pizza");
41+
var boroughFilter = Builders<Restaurant>.Filter.Eq("borough", "Bronx");
42+
var filter = Builders<Restaurant>.Filter.And(cuisineFilter, boroughFilter);
43+
44+
var options = new DistinctOptions {
45+
Comment = "Find all Italian restaurants in the Bronx"
46+
};
47+
48+
var results = collection.Distinct<string>("name", filter).ToList();
49+
foreach (var result in results)
50+
{
51+
Console.WriteLine(result);
52+
}
53+
// end-distinct-with-comment
54+
}
55+
56+
}
57+
58+
private static async void DistinctAsync (IMongoCollection<Restaurant> collection)
59+
{
60+
// start-distinct-async
61+
var results = await collection.DistinctAsync<string>("borough", new BsonDocument());
62+
await results.ForEachAsync(result => Console.WriteLine(result));
63+
// end-distinct-async
64+
}
65+
66+
private static async void DistinctWithQueryAsync (IMongoCollection<Restaurant> collection)
67+
{
68+
// start-distinct-with-query-async
69+
var filter = Builders<Restaurant>.Filter.Eq("cuisine", "Italian");
70+
var results = await collection.DistinctAsync<string>("borough", filter);
71+
await results.ForEachAsync(result => Console.WriteLine(result));
72+
// end-distinct-with-query-async
73+
}
74+
75+
private static async void DistinctWithCommentAsync (IMongoCollection<Restaurant> collection)
76+
{
77+
// start-distinct-with-comment-async
78+
var cuisineFilter = Builders<Restaurant>.Filter.Eq("cuisine", "Pizza");
79+
var boroughFilter = Builders<Restaurant>.Filter.Eq("borough", "Bronx");
80+
var filter = Builders<Restaurant>.Filter.And(cuisineFilter, boroughFilter);
81+
82+
var options = new DistinctOptions {
83+
Comment = "Find all Italian restaurants in the Bronx"
84+
};
85+
86+
var results = await collection.DistinctAsync<string>("name", filter, options);
87+
await results.ForEachAsync(result => Console.WriteLine(result));
88+
// end-distinct-with-comment-async
89+
}
90+
}
91+
92+
// start-restaurant-class
93+
public class Restaurant {
94+
public ObjectId? Id { get; set; }
95+
96+
[BsonElement("name")]
97+
public string? Name { get; set; }
98+
99+
[BsonElement("cuisine")]
100+
public string? Cuisine { get; set; }
101+
102+
[BsonElement("borough")]
103+
public string? Borough { get; set; }
104+
}
105+
// end-restaurant-class

0 commit comments

Comments
 (0)