Experimenting with MongoKitten

As mentioned in my previous post, I have started looking at Server Side Swift with the aim to build a search engine (Burf.co). To store my crawled data I decided to try and use MongoDB as it supports full-text search out of the box. The original Burf.com used Equinox (made by Compsoft) and then later used Microsoft Indexing Service. This time round I wanted to be a little more scalable. Now there are probably better DB solutions for what I plan to do, but MongoDB seemed really simple to get up and running with. Later on, I should be able to switch out the database layer if needed.

MongoKitten

Now that I had decided to use Swift, and MongoDB, I needed to find a framework that connects them, my friend (who knows his stuff) recommended MongoKitten! I got up and running with it fairly quickly even though I don’t know MongoDB too well. Life was good, however, there were a few things I did struggle with:

Contains

So, search a field for a partial string requires you to use Regex (it seems).

Mongo:

db.users.findOne({"username" : {$regex : ".*eBay.*"}});

MongoKitten:

let query: Query = [

"url": RegularExpression(pattern: ".\(eBay).")

]

let matchingEntities: CollectionSlice<Document> = try pages.find(query)

Sorting results on $meta textScore

MongoDB allows you to setup full text searching across your data, it can be across an entire record, or just certain fields (name, address etc). When you perform a full-text search, MongoDB returns the relevant records with an accuracy score ($meta.textScore). MongoDB lets you change how it creates these scores by allowing you to adjust the weights each field receives e.g name is more important than address.

Mongo:

db.pages.find( {$text: {$search: "ebay"}},{score: {$meta: "textScore" }}).sort({score: {$meta:"textScore"}})

MongoKitten:

let query: Query = [

"$text": ["$search": str ],

"lang" : ["$eq": "en"],

]

let projection: Projection = [

“_id”: .excluded,

“url”: “url”,

“title”: “title”,

"score": ["$meta" : "textScore"]

]

let sort: Sort = [

"score": .custom([

“$meta”: “textScore”

])

]

let matchingEntities: CollectionSlice<Document> = try pages.find(query, sortedBy: sort, projecting: projection, readConcern:nil,  collation:nil, skipping: 0, limitedTo: Settings.searchResultLimit )

Getting Help

I found the best way to get help was to contact the creator(Joannis) of MongoKitten via Slack, he is pretty busy but super helpful!

Leave a Reply