mongodb/
db.rs

1pub(crate) mod action;
2pub mod options;
3
4use std::{fmt::Debug, sync::Arc};
5
6use crate::{
7    concern::{ReadConcern, WriteConcern},
8    gridfs::{options::GridFsBucketOptions, GridFsBucket},
9    options::{CollectionOptions, DatabaseOptions},
10    selection_criteria::SelectionCriteria,
11    Client,
12    Collection,
13};
14
15/// `Database` is the client-side abstraction of a MongoDB database. It can be used to perform
16/// database-level operations or to obtain handles to specific collections within the database. A
17/// `Database` can only be obtained through a [`Client`](struct.Client.html) by calling either
18/// [`Client::database`](struct.Client.html#method.database) or
19/// [`Client::database_with_options`](struct.Client.html#method.database_with_options).
20///
21/// `Database` uses [`std::sync::Arc`](https://doc.rust-lang.org/std/sync/struct.Arc.html) internally,
22/// so it can safely be shared across threads or async tasks. For example:
23///
24/// ```rust
25/// 
26/// # use mongodb::{bson::Document, Client, error::Result};
27/// #
28/// #
29/// # async fn start_workers() -> Result<()> {
30/// # let client = Client::with_uri_str("mongodb://example.com").await?;
31/// let db = client.database("items");
32///
33/// for i in 0..5 {
34///     let db_ref = db.clone();
35///
36///     tokio::task::spawn(async move {
37///         let collection = db_ref.collection::<Document>(&format!("coll{}", i));
38///
39///         // Do something with the collection
40///     });
41/// }
42/// #
43/// # Ok(())
44/// # }
45/// ```
46#[derive(Clone, Debug)]
47pub struct Database {
48    inner: Arc<DatabaseInner>,
49}
50
51#[derive(Debug)]
52struct DatabaseInner {
53    client: Client,
54    name: String,
55    selection_criteria: Option<SelectionCriteria>,
56    read_concern: Option<ReadConcern>,
57    write_concern: Option<WriteConcern>,
58}
59
60impl Database {
61    pub(crate) fn new(client: Client, name: &str, options: Option<DatabaseOptions>) -> Self {
62        let options = options.unwrap_or_default();
63        let selection_criteria = options
64            .selection_criteria
65            .or_else(|| client.selection_criteria().cloned());
66
67        let read_concern = options
68            .read_concern
69            .or_else(|| client.read_concern().cloned());
70
71        let write_concern = options
72            .write_concern
73            .or_else(|| client.write_concern().cloned());
74
75        Self {
76            inner: Arc::new(DatabaseInner {
77                client,
78                name: name.to_string(),
79                selection_criteria,
80                read_concern,
81                write_concern,
82            }),
83        }
84    }
85
86    /// Get the `Client` that this collection descended from.
87    pub fn client(&self) -> &Client {
88        &self.inner.client
89    }
90
91    /// Gets the name of the `Database`.
92    pub fn name(&self) -> &str {
93        &self.inner.name
94    }
95
96    /// Gets the read preference of the `Database`.
97    pub fn selection_criteria(&self) -> Option<&SelectionCriteria> {
98        self.inner.selection_criteria.as_ref()
99    }
100
101    /// Gets the read concern of the `Database`.
102    pub fn read_concern(&self) -> Option<&ReadConcern> {
103        self.inner.read_concern.as_ref()
104    }
105
106    /// Gets the write concern of the `Database`.
107    pub fn write_concern(&self) -> Option<&WriteConcern> {
108        self.inner.write_concern.as_ref()
109    }
110
111    /// Gets a handle to a collection in this database with the provided name. The
112    /// [`Collection`] options (e.g. read preference and write concern) will default to those of
113    /// this [`Database`].
114    ///
115    /// For more information on how the generic parameter `T` is used, check out the [`Collection`]
116    /// documentation.
117    ///
118    /// This method does not send or receive anything across the wire to the database, so it can be
119    /// used repeatedly without incurring any costs from I/O.
120    pub fn collection<T: Send + Sync>(&self, name: &str) -> Collection<T> {
121        Collection::new(self.clone(), name, None)
122    }
123
124    /// Gets a handle to a collection in this database with the provided name.
125    /// Operations done with this `Collection` will use the options specified by
126    /// `options` and will otherwise default to those of this [`Database`].
127    ///
128    /// For more information on how the generic parameter `T` is used, check out the [`Collection`]
129    /// documentation.
130    ///
131    /// This method does not send or receive anything across the wire to the database, so it can be
132    /// used repeatedly without incurring any costs from I/O.
133    pub fn collection_with_options<T: Send + Sync>(
134        &self,
135        name: &str,
136        options: CollectionOptions,
137    ) -> Collection<T> {
138        Collection::new(self.clone(), name, Some(options))
139    }
140
141    /// Creates a new [`GridFsBucket`] in the database with the given options.
142    pub fn gridfs_bucket(&self, options: impl Into<Option<GridFsBucketOptions>>) -> GridFsBucket {
143        GridFsBucket::new(self.clone(), options.into().unwrap_or_default())
144    }
145}