Giter Club home page Giter Club logo

mongo-rs's Introduction

Mongo

crates.io Documentation

A higher-level wrapper on top of the official bson & mongodb crates.

Overview

The mongod crate is an unofficial higher-level wrapper that aims to make the bson & mongodb crates a little bit more rust-like.

Provides the following:

  • builder style queries
  • clients with async/non-async support
  • derives for Bson & Mongo to help with BSON type conversion and implentation of traits provided by this crate
  • strong opinions through the use of traits

Example

futures = "0.3"
mongod = { version = "0.3", features = ["derive"] }
tokio = { version = "1.0", features = ["full"] }
use futures::stream::StreamExt;
use mongod::{Bson, Mongo};
use mongod::{AsFilter, AsUpdate, Collection, Comparator, Updates};

#[derive(Debug, Bson, Mongo)]
#[mongo(collection = "users", field, filter, update)]
pub struct User {
  pub name: String,
  pub age: Option<u32>,
}

#[tokio::main]
async fn main() {
  // Create and async client
  let client = mongod::Client::new();

  // Insert a user into the users collection
  let user = User { name: "foo".to_string(), age: None };
  let oid = client.insert_one::<User>(user).await.unwrap();
  println!("{:?}", oid);

  // Fetch all users in the users collection
  let mut cursor = client.find::<User, _>(None).await.unwrap();
  while let Some(res) = cursor.next().await {
      if let Ok((id, user)) = res {
          println!("{} - {:?}", id, user);
      }
  }

  // Update the user
  let mut filter = User::filter();
  filter.name = Some(Comparator::Eq("foo".to_owned()));
  let mut update = User::update();
  update.age = Some(Some(0));
  let updates = Updates {
      set: Some(update),
      ..Default::default()
  };
  let updated = client.update::<User, _, _>(filter, updates).await.unwrap();
  println!("updated {} documents", updated);

  // Delete all users
  let deleted = client.delete::<User, _>(None).await.unwrap();
  println!("delete {} documents", deleted);
}

Client

Async

The default client is async and provides convenience functions over those exposed by the mongodb driver.

Example: see above.

Blocking

Not everything should be async and for that reason a blocking client is provided that can be used at the same time as the async client.

mongod = { version = "0.3", features = ["blocking", "derive"] }
use mongod::{Bson, Mongo};
use mongod::{AsFilter, AsUpdate, Collection, Comparator, Updates};

#[derive(Debug, Bson, Mongo)]
#[mongo(collection = "users", field, filter, update)]
pub struct User {
  pub name: String,
  pub age: Option<u32>,
}

fn main() {
  // Create and async client
  let client = mongo::blocking::Client::new();

  // Insert a user into the users collection
  let user = User { name: "foo".to_string(), age: None };
  let oid = client.insert_one::<User>(user).unwrap();
  println!("{:?}", oid);

  // Fetch all users in the users collection
  let mut cursor = client.find::<User, _>(None).unwrap();
  while let Some(res) = cursor.next() {
      if let Ok((id, user)) = res {
          println!("{} - {:?}", user);
      }
  }

  // Update the user
  let mut filter = User::filter();
  filter.name = Some(Comparator::Eq("foo".to_owned()));
  let mut update = User::update();
  update.age = Some(Some(0));
  let updates = Updates {
      set: Some(update),
      ..Default::default()
  };
  let updated = client.update::<User, _, _>(filter, updates).unwrap();
  println!("updated {} documents", updated);

  // Delete all users
  let deleted = client.delete::<User, _>(None).unwrap();
  println!("delete {} documents", deleted);
}

Complex Queries

Sometimes the convenience queries provided on the client are not enough, the query builders can be used instead.

use mongod::Query;

...

let result = Query::insert::<User>::new()
    .document_validation(false)
    .ordered(false)
    .query(&client, vec![user])
    .await
    .unwrap();

...

Serde

Sometimes there are reasons that implenting TryFrom is just too difficult, but serde implentations already exist. By tweaking the Mongo derive it can be changed to be serde backed.

use mongod::Mongo;

#[derive(Debug, Mongo)]
#[mongo(bson = "serde", collection = "users", field, filter, update)]
pub struct User {
  pub name: String,
  pub age: Option<u32>,
}

...

Too Many Opinions

This library is too opinionated but I wanna use the derives... Well as the derives are basically just fancy ways to convert rust types into BSON, they can be used without the mongod clients. Below is an example of the mongodb client but using a mongod derived user.

use mongod::{Bson, Mongo};
use mongod::Collection;
use mongod::db::Client;

#[derive(Debug, Bson, Mongo)]
#[mongo(collection = "users", field, filter, update)]
pub struct User {
  pub name: String,
}

let client = Client::with_uri_str("mongodb://localhost:27017/").await.unwrap();
let db = client.database("db");
let users = db.collection("users");
let user = User { name: "foo".to_owned() };
let result = users.insert_one(user.into_document().unwrap(), None).unwrap();

TODO

  • Add proc macro tests
  • Not all features have been implented yet...

mongo-rs's People

Contributors

1216892614 avatar alexkornitzer avatar coniesco avatar fscc-alexkornitzer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

mongo-rs's Issues

GridFS support

Is there any chance that you'd be up for supporting GridFS at any time in the future?

Quick question

Found your library while checking the version for mongo and I must say I am impressed. I used to just have a trait that I would use to implement a struct that would represent the collection before using another library that, in a way, simplified it abit more (it was wither) but that from my knowledge is out dated until they update to the official mongodb library.

I would like to know what features would be missing from the crate? I havent used it yet but do plan on implementing it into my application and giving a test run but just curious since in your TODO that it says not all features have been implemented.

Input the database name through a URI

A database name can be included in a mongo URI,

mongodb://$[hostlist]/$[database]?authSource=$[authSource]

The Client struct in this crate seems to aim to operate collections within a single database. Why not just parse the database in the URI to build the Client instead of using the database method of a ClientBuilder?

Return actual type instead of document with `Client::find`

I feel that when Client::find is used that it should return the iterator with the actual type instead of the document. This could be a wrapper around the cursor (maybe similar to how wither does it) or maybe just have it converted into a vector. This should give a more high level feel to the crate since they wouldnt have to convert the document to the type in used with Collection::from_document manually and if they need it they could do it manually. What are your thoughts on it?

no field on type Update when using serde

Hi, I am trying to use Mongo and Bson derived traits while having some of the fields remain handled by serde in order to have customized serialization/de-serialization for that field.

I have a very basic example here:

#[derive(Debug, Serialize, Deserialize)]
pub struct MySerdeType {
    embedded_attr: String
}

#[derive(Debug, Bson, Mongo)]
#[mongo(collection = "my_docs", field, filter, update)]
pub struct MyDoc {
    mongo_attr: String,
    #[mongo(serde)]
    #[bson(serde)]
    serde_attr: MySerdeType
}

Unfortunately, this fails to compile due to 'no field serde_attr on type my_doc::Update'.

If I remove the update attribute, then this compiles, but the model will not implement the AsUpdate or Update traits. Is this expected? Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.