Reputation: 965
I'm working on a tool to sync a collection of Mongo documents to a Postgres database:
extern crate bson;
extern crate mongodb;
use mongodb::{Client, ThreadedClient};
use mongodb::db::ThreadedDatabase;
extern crate docopt;
use docopt::Docopt;
extern crate postgres;
use postgres::{Connection, SslMode};
static USAGE : &'static str = "
USAGE: user_importer --mongo-url <mongo_url> --pg-url <pg_url>
user_importer (--help)
Options:
--mongo-url Mongo Connection URI to the DB that has to users to be imported
--pg-url Postgres Connection URI to mizuna's DB
-h, --help Show this message
";
fn main() {
let argv = std::env::args();
let args = Docopt::new(USAGE).and_then(|d| d.argv(argv).parse()).unwrap_or_else(|e| e.exit());
let mongo_url = args.get_str("<mongo_url>");
let pg_url = args.get_str("<pg_url>");
let pg = Connection::connect(pg_url, SslMode::None).unwrap();
let stmt = pg.prepare("INSERT INTO mongo_users (mongo_id, email, name, sfdc_id) VALUES ($1, $2, $3, $4)").unwrap();
let mongo = Client::with_uri(mongo_url)
.ok().expect("Failed to initialize client.");
let coll = mongo.db("napa").collection("users");
let cursor = coll.find(None, None).unwrap();
for result in cursor {
if let Ok(item) = result {
println!("{:?}", item.get("_id").unwrap());
println!("to_string {:?}", item.get("_id").unwrap().to_string());
println!("to_json {:?}", item.get("_id").unwrap().to_json());
let mongo_id = item.get("_id").unwrap().to_string();
let email = item.get("email").map(|s| s.to_string());
let name = item.get("name").map(|s| s.to_string());
let sfdc_id = item.get("sfdc_id").map(|s| s.to_string());
stmt.execute(&[&mongo_id, &email, &name, &sfdc_id]).unwrap();
}
}
}
The part I'm having trouble with is converting the document's _id
field to a hex string (Line 43). It seems that item.get("_id")
returns an object of type BSON
, which has a few converters: to_string()
returns ObjectId("566740710ed3bc0a8f000001")
, and to_json()
returns {"$oid": "566740710ed3bc0a8f000001"}
, neither of which are the plan hex string that I want to insert. I see in the docs that ObjectId
has a to_hex()
function, but I can't figure out how to get from the get()
method's BSON
return type to the underlying ObjectId
type that has that method implemented.
Upvotes: 1
Views: 4021
Reputation: 819
With serde data model example.
let id: ObjectId = customer.id.unwrap();
let str_id: String = id.to_hex();
One line.
let str_id = customer.id.unwrap().to_hex();
The model example definition:
#[derive(Serialize, Deserialize)]
pub struct Customer {
#[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
pub id: Option<ObjectId>,
pub name: String,
...
}
Upvotes: 0
Reputation: 127831
Use OrderedDocument::get_object_id()
method:
let mongo_id = item.get_object_id("_id").unwrap();
let mongo_id_hex = mongo_id.to_hex();
It is sad that bson-rs does not have any docs published anywhere.
Upvotes: 3
Reputation: 65782
The get()
methods returns an Option<&Bson>
. Bson
is an enum
, so in order to access the data in a variant, you need to use pattern matching with match
or if let
.
let mongo_id =
match *item.get("_id").unwrap() {
Bson::ObjectId(oid) => oid,
_ => panic!("_id is not an ObjectId!"),
};
This initializes mongo_id
with the ObjectId
value for the _id
field.
Upvotes: 2