Mongo

A quick post so I can remember how to do stuff with the mongo db dump now available on Open Food Facts.
This is a quick dump of an IRB session (not the International Rugby Board, but the Interactive Ruby Shell).

require 'mongo'
client = Mongo::MongoClient.new
=> #<Mongo::MongoClient:0x00000001fc6218 @host="localhost", @port=27017, @id_lock=#<Mutex:0x00000001fc5cf0>, @primary=["localhost", 27017], @primary_pool=#<Mongo::Pool:0xfe4c3c @host=localhost @port=27017 @ping_time= 0/1 sockets available up=true>, @mongos=false, @tag_sets=[], @acceptable_latency=15, @max_bson_size=16777216, @max_message_size=nil, @max_wire_version=nil, @min_wire_version=nil, @max_write_batch_size=nil, @slave_ok=nil, @ssl=nil, @unix=false, @socket_opts={}, @socket_class=Mongo::TCPSocket, @db_name=nil, @auths=#<Set: {}>, @pool_size=1, @pool_timeout=5.0, @op_timeout=nil, @connect_timeout=30, @logger=nil, @read=:primary, @write_concern={:w=>1}, @read_primary=true>
# List database available
client.database_names
=> ["test", "local"]
# Select a database to work on
db = client["test"]
=> #<Mongo::DB:0x0000000200ef90 @name="test", @client=#<Mongo::MongoClient:0x00000001fc6218 @host="localhost", @port=27017, @id_lock=#<Mutex:0x00000001fc5cf0>, @primary=["localhost", 27017], @primary_pool=#<Mongo::Pool:0xfe4c3c @host=localhost @port=27017 @ping_time= 0/1 sockets available up=true>, @mongos=false, @tag_sets=[], @acceptable_latency=15, @max_bson_size=16777216, @max_message_size=nil, @max_wire_version=nil, @min_wire_version=nil, @max_write_batch_size=nil, @slave_ok=nil, @ssl=nil, @unix=false, @socket_opts={}, @socket_class=Mongo::TCPSocket, @db_name=nil, @auths=#<Set: {}>, @pool_size=1, @pool_timeout=5.0, @op_timeout=nil, @connect_timeout=30, @logger=nil, @read=:primary, @write_concern={:w=>1}, @read_primary=true>, @strict=nil, @pk_factory=nil, @write_concern={:w=>1}, @read=:primary, @tag_sets=[], @acceptable_latency=15, @cache_time=300>
# List collections (table from SQL people)
db.collection_names
=> ["products", "system.indexes"]
# Select a collection to work on
products = db["products"]
=> #<Mongo::Collection:0x0000000205e720 @name="products", @db=#<Mongo::DB:0x0000000200ef90 @name="test", @client=#<Mongo::MongoClient:0x00000001fc6218 @host="localhost", @port=27017, @id_lock=#<Mutex:0x00000001fc5cf0>, @primary=["localhost", 27017], @primary_pool=#<Mongo::Pool:0xfe4c3c @host=localhost @port=27017 @ping_time= 0/1 sockets available up=true>, @mongos=false, @tag_sets=[], @acceptable_latency=15, @max_bson_size=16777216, @max_message_size=nil, @max_wire_version=nil, @min_wire_version=nil, @max_write_batch_size=nil, @slave_ok=nil, @ssl=nil, @unix=false, @socket_opts={}, @socket_class=Mongo::TCPSocket, @db_name=nil, @auths=#<Set: {}>, @pool_size=1, @pool_timeout=5.0, @op_timeout=nil, @connect_timeout=30, @logger=nil, @read=:primary, @write_concern={:w=>1}, @read_primary=true>, @strict=nil, @pk_factory=nil, @write_concern={:w=>1}, @read=:primary, @tag_sets=[], @acceptable_latency=15, @cache_time=300>, @connection=#<Mongo::MongoClient:0x00000001fc6218 @host="localhost", @port=27017, @id_lock=#<Mutex:0x00000001fc5cf0>, @primary=["localhost", 27017], @primary_pool=#<Mongo::Pool:0xfe4c3c @host=localhost @port=27017 @ping_time= 0/1 sockets available up=true>, @mongos=false, @tag_sets=[], @acceptable_latency=15, @max_bson_size=16777216, @max_message_size=nil, @max_wire_version=nil, @min_wire_version=nil, @max_write_batch_size=nil, @slave_ok=nil, @ssl=nil, @unix=false, @socket_opts={}, @socket_class=Mongo::TCPSocket, @db_name=nil, @auths=#<Set: {}>, @pool_size=1, @pool_timeout=5.0, @op_timeout=nil, @connect_timeout=30, @logger=nil, @read=:primary, @write_concern={:w=>1}, @read_primary=true>, @logger=nil, @cache_time=300, @cache={}, @write_concern={:w=>1}, @read=:primary, @capped=nil, @tag_sets=[], @acceptable_latency=15, @pk_factory=BSON::ObjectId, @hint=nil, @operation_writer=#<Mongo::CollectionOperationWriter:0x0000000205e5b8 @collection=#<Mongo::Collection:0x0000000205e720 ...>, @name="products", @db=#<Mongo::DB:0x0000000200ef90 @name="test", @client=#<Mongo::MongoClient:0x00000001fc6218 @host="localhost", @port=27017, @id_lock=#<Mutex:0x00000001fc5cf0>, @primary=["localhost", 27017], @primary_pool=#<Mongo::Pool:0xfe4c3c @host=localhost @port=27017 @ping_time= 0/1 sockets available up=true>, @mongos=false, @tag_sets=[], @acceptable_latency=15, @max_bson_size=16777216, @max_message_size=nil, @max_wire_version=nil, @min_wire_version=nil, @max_write_batch_size=nil, @slave_ok=nil, @ssl=nil, @unix=false, @socket_opts={}, @socket_class=Mongo::TCPSocket, @db_name=nil, @auths=#<Set: {}>, @pool_size=1, @pool_timeout=5.0, @op_timeout=nil, @connect_timeout=30, @logger=nil, @read=:primary, @write_concern={:w=>1}, @read_primary=true>, @strict=nil, @pk_factory=nil, @write_concern={:w=>1}, @read=:primary, @tag_sets=[], @acceptable_latency=15, @cache_time=300>, @connection=#<Mongo::MongoClient:0x00000001fc6218 @host="localhost", @port=27017, @id_lock=#<Mutex:0x00000001fc5cf0>, @primary=["localhost", 27017], @primary_pool=#<Mongo::Pool:0xfe4c3c @host=localhost @port=27017 @ping_time= 0/1 sockets available up=true>, @mongos=false, @tag_sets=[], @acceptable_latency=15, @max_bson_size=16777216, @max_message_size=nil, @max_wire_version=nil, @min_wire_version=nil, @max_write_batch_size=nil, @slave_ok=nil, @ssl=nil, @unix=false, @socket_opts={}, @socket_class=Mongo::TCPSocket, @db_name=nil, @auths=#<Set: {}>, @pool_size=1, @pool_timeout=5.0, @op_timeout=nil, @connect_timeout=30, @logger=nil, @read=:primary, @write_concern={:w=>1}, @read_primary=true>, @logger=nil, @max_write_batch_size=1000>, @command_writer=#<Mongo::CollectionCommandWriter:0x0000000205e590 @collection=#<Mongo::Collection:0x0000000205e720 ...>, @name="products", @db=#<Mongo::DB:0x0000000200ef90 @name="test", @client=#<Mongo::MongoClient:0x00000001fc6218 @host="localhost", @port=27017, @id_lock=#<Mutex:0x00000001fc5cf0>, @primary=["localhost", 27017], @primary_pool=#<Mongo::Pool:0xfe4c3c @host=localhost @port=27017 @ping_time= 0/1 sockets available up=true>, @mongos=false, @tag_sets=[], @acceptable_latency=15, @max_bson_size=16777216, @max_message_size=nil, @max_wire_version=nil, @min_wire_version=nil, @max_write_batch_size=nil, @slave_ok=nil, @ssl=nil, @unix=false, @socket_opts={}, @socket_class=Mongo::TCPSocket, @db_name=nil, @auths=#<Set: {}>, @pool_size=1, @pool_timeout=5.0, @op_timeout=nil, @connect_timeout=30, @logger=nil, @read=:primary, @write_concern={:w=>1}, @read_primary=true>, @strict=nil, @pk_factory=nil, @write_concern={:w=>1}, @read=:primary, @tag_sets=[], @acceptable_latency=15, @cache_time=300>, @connection=#<Mongo::MongoClient:0x00000001fc6218 @host="localhost", @port=27017, @id_lock=#<Mutex:0x00000001fc5cf0>, @primary=["localhost", 27017], @primary_pool=#<Mongo::Pool:0xfe4c3c @host=localhost @port=27017 @ping_time= 0/1 sockets available up=true>, @mongos=false, @tag_sets=[], @acceptable_latency=15, @max_bson_size=16777216, @max_message_size=nil, @max_wire_version=nil, @min_wire_version=nil, @max_write_batch_size=nil, @slave_ok=nil, @ssl=nil, @unix=false, @socket_opts={}, @socket_class=Mongo::TCPSocket, @db_name=nil, @auths=#<Set: {}>, @pool_size=1, @pool_timeout=5.0, @op_timeout=nil, @connect_timeout=30, @logger=nil, @read=:primary, @write_concern={:w=>1}, @read_primary=true>, @logger=nil, @max_write_batch_size=1000>>
# Count the product from France
products.find("countries" => /.rance/).count
=> 15342

That's it folks

Mem Athon

A while back I started learning Polish with the help of a website called memrise.
While I didn’t persevere, my partner got a hang for it and used it far more than I did.
It feature course, for a multitude of languages.
Some course contains the 2000 words required to pass at A-level.
Some aim at giving you vocabulary on certain topic and contain far less words.
Then memrise, provide you with an interface that allow you to see, hear and associate a word with an image, called a ‘mem’.
Then you go throught a list of questions, sometime finding the source-language word, sometime the target language word.
Then it goes one knot up, when you need have the source language and you need to write the word in the target language yourself.
The more you get a word right, the more the little seed icon grows into a full blown flower.
Once a word is a ‘flower’, it means it should be in your long term memory.
The learning occur a few set of words at a time, from a couple to maybe a dozen max.
You can do a few sequence in a row, or just take a break to let it simmer.
At some point, you will need to review the words you just learned, maybe at the end of the day, maybe at the begining, and there is a feature just to do that.

Overall I think the interface does a good job getting out of the way.
I cannot play the sounds on my machine, still I can wget them.
I don’t like most of the ‘mem’, but I keep an eye on them nevertheless.
I just which that the word would be repeated everytime you get the answer right.
Finally, there is a weekly/monthly/all time leaderboard, to compare with other member of the site.

I’m currently trying to compare myself against Ed Cooke, the founder of memrise. He is trying to learn 2000 polish words in 10 days.
He started yesterday and already is leading the way for this week.
I’m happy to say that since I started this afternoon I learned 42 words :)

Happy learning!

Vampires

Vampires, Vampires, Vampires!
I even like saying the word vampires!

I found it really interesting that we colectivelly kept and nurtured the vampire social allegory.
Not just the ones we picture in films and books nowadays, but the one that exists in one form or another accross the world since time immemorial.

Our ancestor gaves us clues to figure something out. Why is so crucial that we need to know how to spot ‘vampire’, to understand the tactics used to lure us and to realise what lies ahead for those who get charmed.
But who exactly are the ‘vampires’ of our world?

I’ve been pondering on the whole ‘vampires’ as of late.
It started with the reading of children of the fight blog post from Pieter Hintjens (known for his work on MQs).
If you haven’t already I would strongly advice that you read it now.
You should then logically read the second part called From Dusk till Dawn .
After reading Peter’s articles, I was able to put 2 names on the description offered.
Can you?

It is to say some humans behave like vampires or ‘psycopath’ as Peter put it. Psycopath, narcissist, Machiavellian, sociopath, is the far less romanticise version that our society has to offer.

He goes and state that is difficult to spot them, as they hide in plain sight, unlike the mythical sun avoiding creatures.
We, mere humans, are different from them with our empaty, sense of humour and love for the art. One thing is clear, they will cause mental illness in others, in the form of depression, PTSD, and suicidal urges. If you doubt it, just work for the financial sector for a bit .

So who are those 2 people that struck me as ‘vampires’ ? Let see what they share, and how they fit the ‘sociopath’ description.
Both are in a position of power.
Both seems to lack basic sense of humour, they don’t laught.
Unless it is at someone’s expense they don’t really make jokes.
And when they do, only their minions laught.
Yeah both have at least one minion, see renfield?
They don’t really seem to care for their familly life, or keep it very, very private.
Finally, both show blatant apathy for the (little) world their reigned upon.
Basically, they don’t really care how detrimental it could be for other, as long as it leads to what they consider success for themselves.
A this point, you are probably not really reading this anymore. Hopefully you are now thinking about the one in your environment that fit the bill.
Then I started to think, am I on too?

Could it be possible that I’m unknowingly part of the vampire crew.
If it is my nature, I might well not realise that I’m one myself.
Solace came in the unconspicuious unpaired socks in my drawer.
So I’m not a ‘natural vampire’ in a dracula sort of way.
Maybe I wasn’t paying attention and I became one?
In a ‘getting turned by vampire into one’ kind of way.
I did spend a fair amount of time in the vincinity of ‘psycopath’.
I don’t belive that I became one (so far), maybe not for me to tell?

How to do you make sure you don’t get turned into one then? I don’t know, yet I doubt its done through the use of garlic. I would put my money on the threshold rule. Not opening one’s door to a psycopath, surely help not to let a psycopath enter’s one life. Logically next step is to make sure I don’t end up stuck with a management that fitsthe depicted character description ever again. I doubt I can avoid psycopath altogether, but as they are outnumbered, I’m sure I can minimise their effect one my life.

We can colelctivelly acknoledge that ‘psycopath’ exist, but are they just too real to be faced as what they are? Maybe we still need the ‘vampire’ allegory. Even if it carries some cultural burden attached to a bunch of cluttered notion from a 18th century fearing society.

Hopefully by now, you are thinking about watching a good old vampire movie Well if you don’t you might be one of them ;) I would strongly recommend you to buy this film and maybe watch “only lovers left alive”.
Both provide a satisfing new view on the topic that completly depart from the whole narative of this blog post

TL;DR: Vampires are overdone as genre in the Arts, the same way this door is overdoing the use warning sings for a probably good reason.

Going Clutter Free

Over the last month I started to go some inbox cleanup.
The goal is to avoid getting interrupted by email every minute.
That include unsubscribing from more than 60 mailing lists, 40 google groups, a dozen github project, meetup emails, amazon, ebay, twitter and other commercial product emails.

There is a few open source project that I also put asside.
I didn’t contribute much to The Foreman, but I kept a tab on it.
Now I likely won’t anytime soon, so I choose to stop subscribing to the project mailing list, github etc…

I’m also leaving the “Open Company Initiative” project.
There has been few controversies, mainly with the project leader in the past.
While not happening on the “OCI” directly but on gittip/gratipay.
Gittip/gratipay is similar to “patreon”, “subbable”, “tipeee”, “flattr”: it helps people to get access to funds etc…

I didn’t put the effort to understand why or what was going on at the time.
Here is the summary of one such event.
Other people have come forward to voice their concern.
An astute reader might realise that I’m leaving one project because of something that happened in annother project.
Firstly, the leader is the same for both project.
Secondly the governance is left (purposely?) unclear, for both project.
Finally gratipay is meant to be an exemple of “open company”.

Do I really want to be part of a initiative that use as an example a company hostinga well known community that trhive on doxing people and hosting CP?
I don’t want to be involve with such a company from close or far.
But that is not remotly as bad as being involve with the person in charge.
If you want to understand the situation better, you might want to set some time asside and read this gratipay github issue.
Views that that find it OK to host “killer if they don’t kill on my website” are antagonistics with mine.

To end this post with a more positive note, I’m still going to follow what the crewmate people are doing.
I’m also getting involved in another project that has to do with food.
Stay tune for more.

Geckoboard

Today I've been looking at geckoboard once more.
I looked at it a while back.
I also met some of the team at the silicon milkroundabout 6.0.
I got a free (purple) T-shirt then, maybe very happy :)

So looking back at it now, I didn't expect so many services.
Maybe I just didn't noticed them before, maybe I just wasn't interrested enought, I don't know.
I was particulary keen to see google analytics as I use it for my dad's online presence’s analytics.
So far it has been a treat.
I can do a clutter free, login free, simple dashboard.
With a bit of DNS wizzardry I could even get to dashboard with a simple URL.

I'm not using it massivelly, just enought to give some vanity metrics to my dad.
Basically I was using what Google Analytics provided. I got an email delivered every morning(ish) to both of us.
The good thing is my dad like email, the bad thing is that I already have enought emails.
Plus I have it delivered as two pdf with is not really great eaither.
The other way is to use the builtin dashboard.
I don't particulary want to log in and drill down into google analytics, life is too short for that.
Also the formating was not of my liking.
So overall, not a great experience.

I had a good idea of what I needed, sessions over different time scale, page view and time per page, country of origin.
Then, I need to be able to remove bouncing traffic.
So i went on my merry way, and did the dashboard.
Once there, I remmembered it was general availability for dommain names in .bzh.
Now I needed another dashboard, well the same one with a different target in my google analytics.
It was easy to clone the dashboard, but then it was a bit tiresome to go to each widget and change the target.
It could be configurable per dashboard.
Of course that would require more settings, more UI clutter etc.
Maybe an advance mode to be able to do batch, or maybe over an API for those who need it.
Well not that anoying in the end (just time consuming).

There is a page that help with Google Analytics. It also link to a pdf, where you learn dashboard 101.
This page details operators, dimensions and metrics one can use to create a filter.
It also provides definition of the available widget.
It is well made and insightfull.

I think that's being a company help to provide educational material.
Most of the open source project don't even have a place holder for that.
There is often documentation, but it mostly revolve around technical details like implementation details, installation and operations advice.
This is why confereces and talks are an essential part of open source in general.
So open source dashboard will not come with a huge amount of materials, but you can find it. You probably will also get to know the source of the knowlegde, like which video to watch, which book to read to go further into knowledge etc. That s how I got to read Information Dashboard Design by Stephen Few.

Overall I think Geckboard does a very good job at explaining workflow too.
At the begining you put everything you can (the same way you “log all the things”). Then you try to make sense of it. You realise it is cluttered and make some cleaning. Finally you revisit your dashboard often so they remain relevant.

They also are of good advice. They recomend that you split your dashboard by audiance. Your boss and the boss of your boss don’t have the same need. Also the dashboard type can be different. The dashboard to check if your service are up and running are hopefully not the same one you look at when you try to undertand what your customer are like today. It’s well explain in a neat 6 rules set

You can also do custom graphs with geckoboard.
One of them is my favorite one in the whole world the bullet-graph.
While I think the name is wrong, this type of graph provides some of the most condenced informaton rich graph ever.
This is from wikipedia: “The bullet graph features a single, primary measure (for example, current year-to-date revenue), compares that measure to one or more other measures to enrich its meaning (for example, compared to a target), and displays it in the context of qualitative ranges of performance, such as poor, satisfactory, and good. The qualitative ranges are displayed as varying intensities of a single hue to make them discernible by those who are color blind and to restrict the use of colors on the dashboard to a minimum.”

I have no use for the ranges under the bullet graph bar in my dashbaord, hence I didn't use it.
I don't have conversion goals or expectation out of page views/sessions etc.
Still it is available and that can only noted as a good understanding power a dashboard can provide.
On the other side, the Geck-o-Meter, a Tachometer is also available.
And unless they are many people displaying speed with Geckoboard, it's probably not for the best.
Actually same goes for pie chart, they are bad and should be banned.
Any kind of bar or sparkline would do the same job, with more data in a smaller space.
If you are not sure why you don't want to waste space, watch this talk by Jarkko Laine.
Actually go watch all the video from monitorama and monitorama.eu.

Finally I looked at polling data from APIs. So far I find it quite limiting.
Geckoboard expect you to create an API, and you to pull from it. Not say poll from github or the other people that you depend on and graph that.
They actually expect ‘Items’ like in this exemple:

{
  "item": [
    {
      "text": "Unfortunately, as you probably already know, people",
      "type": 0
    },
    {
      "text": "As you might know, I am a full time Internet",
      "type": 1
    }
  ]
}

It means that if you want to consume say, github api:

{
  "status": "good",
  "last_updated": "2012-12-07T18:11:55Z"
}

I also checked the push options for widget.
I found an sinatra app on the geckboard twiter.
I even made a pull request because the link to the documentation was now outdated.
That done I also added a bit more information about where to get the API and Widget key.
Finally I uploaded the code to openshift.
Here it is, a geckoboard push api tester.

What is missing ? * A way to do snapshot (to come back to a previous state) * commit messages (as in git commit message) when you do change the dashboard. * Tooltips: it is definitly missing to give more understanding of the data. Especially to explain the secondary number (one might no know the period the primary number is compared to) * The possibility to fiddle with the api polling results. * A middle price tag for individual with more than 1 dashboard, but say less than 60 quid a month to spend on a rather nice dashboard.

There are alternatives.
One of my favorite one is dashing if you have the possibility to run it by yourself.
If you like geckboard and would like 10% off, you can always use this link.