views:

159

answers:

2

I wanted to add user search auto-complete (like Facebook's) to my Rails app on Heroku, and I chose to write it in Node.js because of the concurrency requirements. The search first pulls a user's friend list (of id's, which include all twitter friends, not just their friends on our site) from Mongo, then searches for users in that list, then does another search for any other users that match the query that weren't in the results returned by the friends search.

This was fairly fast at first (~150 ms), but for users with more friends (above, say, 100 total), loading their friends array ended up being a huge bottleneck, linearly slowing down the search to a maximum of around 1500 ms for user's with 1,000 friends (the maximum number supported for autocomplete friends search).

The problem is, I'm completely new to Node.js and Express (its Sinatra-like web framework), and I have no idea how to cache the friends array so I only need to load it once (ideally into memory). In Rails on Heroku I'd simply load the array into Memcache, but I'm not even sure how to configure Memcache in Node/Express, let alone if that's supported on Heroku.

Any ideas?

(Also note, I'm multi-key indexing for all these queries, including the friends ids)

+1  A: 

I know very little about Node.js or Express. However, I can tell you that you probably want to do this client-side. (i.e.: cookie the friends list on the client and use javascript to search)

If you look at FB's implementation, this is what they're doing (at least they were several months ago).

Gates VP
+2  A: 

I imagine mongodb would be the place to have the matching done. It seems like you are trying to get all of the results back into your own code, and then match them yourself in an array. You will probably find it faster to ask mongodb to filter out the top 10 matching results for you and then send those direcectly to the client.

The best part about databases is that they can do this filtering for you and quickly. And it should scale well beyond other solutions. Trust the database, the whole point of mongodb is that the query should be blazingly fast and close to the speed of memcache. You just need to ask it the right question. And I imagine you can hammer the database hard, but make sure to request only the exact # of matches you are intending to use.

To match John Smi... Maybe something like this (I just made this up to show the idea):

friendIdList //Assumed to be a simple array of ids from your app

var matchFriends = db.people.find( { person_id : { $in : friendIdList }, name : /john smi.*/i } ).sort( { name : 1 } ).limit(10);

See the mongodb docs on regular expression queries

hope this helps, I am just learning about mongodb and not an expert, but this is how I would approach the problem on other databases

orangutancloud