I recently had the chance to go to Riviera Dev, a fantastic developer conference taking place near the French Riviera. Couchbase sponsored the conference, we brought organic, local, goat milk ice-cream. People were happy, talks were interestings, SWAG was given out. It was an amazing conference.
When we sponsor conferences with such activities, we usually ask attendees if we can scan their badges to send them some Couchbase updates. So we did. And sometimes the information is easy to recover, sometimes it’s a bit tricky. Here, the QR code contained a VCard. Their purpose is to hold contact information, precious information – as you know, scans are the currency of conferences. It’s what allows us to come back the following year with even more ice cream.
Anyway, we ended up collecting a lot of VCards but it was hard to put them in the ubiquitous marketing format, CSV. So what do you do when you need to manipulate data? You use Couchbase Shell.
Couchbase Shell, Shell Yeah!
Couchbase Shell (cbsh) is a modern, productive, and fun shell for Couchbase Server and Capella (our cloud DBaaS). The source code and instructions to install it are available on the repo Readme.
I personally installed it by cloning and building it:
1 2 3 |
git clone https://github.com/couchbaselabs/couchbase-shell cd couchbase-shell cargo install --path . |
You need to have the Rust toolchain installed, because Couchbase Shell is written in Rust, and based on my favorite shell, nushell.
Once installed, you can run it by typing cbsh
. It will ask you to configure a Couchbase connection first. If you are using the Capella management interface, you will get all required information in the Connect tab.
Nushell <3 JSON
For the record, this is what my VCard looks like:
1 2 3 4 5 6 |
BEGIN:VCARD VERSION:2.1 N:DOGUIN;Laurent;;; ORG:Couchbase EMAIL;INTERNET:laurent.doguin@couchbase.com END:VCARD |
There are plenty of node libraries to turn this to JSON, I have used vcard-json. So if I run node de vcard2json.js
, I get a JSON array with all VCard content as a JSON object.
Which is great but how can this be manipulated easily? Cbsh being based on nushell, we get all the good things that come with it, like the from json
command, or the where
filter, and the JSON select
. So let’s see how it would work step by step, with the structured data output, also courtesy of nushell:
1 2 3 4 5 |
👤 Laurent Doguin 🏠 capella > node vcard2json.js [{"name":{"surname":"Doguin","name":"Laurent","additionalName":"","prefix":"","suffix":""},"organization":"Couchbase","email":[{"isDefault":false,"valueInfo":{},"value":"laurentdoguin@couchbase.com"}]},{"name":{"surname":"This","name":"Person","additionalName":"","prefix":"","suffix":""},"organization":"DoesNotWorkAtCouchbase","email":[{"isDefault":false,"valueInfo":{},"value":"thiperson@notcouchbase.com"}]}] |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
👤 Laurent Doguin 🏠 capella > node vcard2json.js | from json ╭───┬──────────────────────────────┬────────────────────────┬─────────────────────────────────────────────────────────────────────╮ │ # │ name │ organization │ email │ ├───┼──────────────────────────────┼────────────────────────┼─────────────────────────────────────────────────────────────────────┤ │ 0 │ ╭────────────────┬─────────╮ │ Couchbase │ ╭───┬───────────┬───────────────────┬─────────────────────────────╮ │ │ │ │ surname │ Doguin │ │ │ │ # │ isDefault │ valueInfo │ value │ │ │ │ │ name │ Laurent │ │ │ ├───┼───────────┼───────────────────┼─────────────────────────────┤ │ │ │ │ additionalName │ │ │ │ │ 0 │ false │ {record 0 fields} │ laurentdoguin@couchbase.com │ │ │ │ │ prefix │ │ │ │ ╰───┴───────────┴───────────────────┴─────────────────────────────╯ │ │ │ │ suffix │ │ │ │ │ │ │ ╰────────────────┴─────────╯ │ │ │ │ 1 │ ╭────────────────┬────────╮ │ DoesNotWorkAtCouchbase │ ╭───┬───────────┬───────────────────┬────────────────────────────╮ │ │ │ │ surname │ This │ │ │ │ # │ isDefault │ valueInfo │ value │ │ │ │ │ name │ Person │ │ │ ├───┼───────────┼───────────────────┼────────────────────────────┤ │ │ │ │ additionalName │ │ │ │ │ 0 │ false │ {record 0 fields} │ thiperson@notcouchbase.com │ │ │ │ │ prefix │ │ │ │ ╰───┴───────────┴───────────────────┴────────────────────────────╯ │ │ │ │ suffix │ │ │ │ │ │ │ ╰────────────────┴────────╯ │ │ │ ╰───┴──────────────────────────────┴────────────────────────┴─────────────────────────────────────────────────────────────────────╯ |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
👤 Laurent Doguin 🏠 capella > node vcard2json.js | from json | where organization != 'Couchbase' ╭───┬─────────────────────────────┬────────────────────────┬────────────────────────────────────────────────────────────────────╮ │ # │ name │ organization │ email │ ├───┼─────────────────────────────┼────────────────────────┼────────────────────────────────────────────────────────────────────┤ │ 0 │ ╭────────────────┬────────╮ │ DoesNotWorkAtCouchbase │ ╭───┬───────────┬───────────────────┬────────────────────────────╮ │ │ │ │ surname │ This │ │ │ │ # │ isDefault │ valueInfo │ value │ │ │ │ │ name │ Person │ │ │ ├───┼───────────┼───────────────────┼────────────────────────────┤ │ │ │ │ additionalName │ │ │ │ │ 0 │ false │ {record 0 fields} │ thiperson@notcouchbase.com │ │ │ │ │ prefix │ │ │ │ ╰───┴───────────┴───────────────────┴────────────────────────────╯ │ │ │ │ suffix │ │ │ │ │ │ │ ╰────────────────┴────────╯ │ │ │ ╰───┴─────────────────────────────┴────────────────────────┴────────────────────────────────────────────────────────────────────╯ |
1 2 3 4 5 6 7 |
👤 Laurent Doguin 🏠 capella > node vcard2json.js | from json | where organization != 'Couchbase' | select name.name name.surname organization email.0.value ╭───┬───────────┬──────────────┬────────────────────────┬────────────────────────────╮ │ # │ name_name │ name_surname │ organization │ email_0_value │ ├───┼───────────┼──────────────┼────────────────────────┼────────────────────────────┤ │ 0 │ Person │ This │ DoesNotWorkAtCouchbase │ thiperson@notcouchbase.com │ ╰───┴───────────┴──────────────┴────────────────────────┴────────────────────────────╯ |
Now that the data is ready and cleaned-up, what can I do with it ? I could write this to a CSV file like this:
1 |
> node vcard2json.js | from json | where organization != 'Couchbase' | select name.name name.surname organization email.0.value | to csv| save contacts.csv |
I could also write it to Couchbase. I have my credential all set already. The first command chooses the bucket and default scope and collection. The second one iterates through the JSON array, generates a random UUID, wraps the content under a content column and adds an ID column with the generated UUID, then inserts the result in Couchbase.
1 2 3 |
👤 Laurent Doguin 🏠 capella > cb-env bucket vcard |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
👤 Laurent Doguin 🏠 capella in ☁️ vcard._default._default > node vcard2json.js | from json | where organization != 'Couchbase' |select name.name name.surname organization email.0.value |rename firstname lastname organization email | each { |it| let uuid = {random uuid}; $it | wrap content| insert id $uuid | doc upsert } ╭───┬───────────────────────────────────────────────────────────╮ │ 0 │ ╭───┬───────────┬─────────┬────────┬──────────┬─────────╮ │ │ │ │ # │ processed │ success │ failed │ failures │ cluster │ │ │ │ ├───┼───────────┼─────────┼────────┼──────────┼─────────┤ │ │ │ │ 0 │ 1 │ 1 │ 0 │ │ capella │ │ │ │ ╰───┴───────────┴─────────┴────────┴──────────┴─────────╯ │ │ 1 │ ╭───┬───────────┬─────────┬────────┬──────────┬─────────╮ │ │ │ │ # │ processed │ success │ failed │ failures │ cluster │ │ │ │ ├───┼───────────┼─────────┼────────┼──────────┼─────────┤ │ │ │ │ 0 │ 1 │ 1 │ 0 │ │ capella │ │ │ │ ╰───┴───────────┴─────────┴────────┴──────────┴─────────╯ │ ╰───┴───────────────────────────────────────────────────────────╯ |
And just to make sure it’s working, the data can be queried with SQL++ directly:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
👤 Laurent Doguin 🏠 capella in ☁️ vcard._default._default > query "SELECT * from `vcard`" ╭───┬────────────────────────────────────────────────┬─────────╮ │ # │ vcard │ cluster │ ├───┼────────────────────────────────────────────────┼─────────┤ │ 0 │ ╭──────────────┬─────────────────────────────╮ │ capella │ │ │ │ firstname │ Person1 │ │ │ │ │ │ lastname │ LastNa │ │ │ │ │ │ organization │ Organisat │ │ │ │ │ │ email │ person1lastna@couchbase.com │ │ │ │ │ ╰──────────────┴─────────────────────────────╯ │ │ │ 1 │ ╭──────────────┬────────────────────────────╮ │ capella │ │ │ │ firstname │ Person │ │ │ │ │ │ lastname │ This │ │ │ │ │ │ organization │ DoesNotWorkAtCouchbase │ │ │ │ │ │ email │ thiperson@notcouchbase.com │ │ │ │ │ ╰──────────────┴────────────────────────────╯ │ │ ╰───┴────────────────────────────────────────────────┴─────────╯ |
So there you are, a practical example of using Couchbase Shell to manipulate Data, transform it and import it to Couchabse. But there are plenty of other uses for it! What’s your favorite?