Autocomplete a field using a mongodb


#1

I have a list of ~10000 stocks. They have a ticker values like : BB or DRG_UN, which is linked to a name, “Blackberry” and “Dream Realty” for this example.

How can I take someone writing either the ticker or the name into a input field, and returning the ticker? I have the table stored as a CSV currently, but also as a mongo collection.


#2

I’ve also been looking into using typeahead, or anything really that can provide an autocomplete function. Most things seem deprecated though.


#3

I am using jQuery UI autocomplete and it works well


#4

I’ve reduced the size of my table to ~5100 key value pairs, have it in both a mongoDB and a CSV. Do you think it would be happy with taking arrays of that size?


#5

Here is a small example how I use it in my application. Assuming you have the following template

<template name="massiveCollectionTypeahead">
  <input type="text" name="autocomplete"  class="form-control autocomplete" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" placeholder="Enter Search String"/>
</template>

You can wire up the autocomplete like so

if(Meteor.isClient) {
  // choosing a Session value to trigger action when autocomplete has been selected
  Session.setDefault('massiveCollectionTypeahead',null);

  Template.massiveCollectionTypeahead.onRendered(function(){
    var self = this;

    var $autocomplete = self.$('.autocomplete');

    $autocomplete.autocomplete({
      minLength: 2,
      autoFocus: true,
      // you might have to adjust the appendTo to match your setup
      appendTo: $autocomplete.parent().parent(),
      // the actual magic to generate the autocomplete
      source: function(request, callback){
        // instead of rendering this with a massive array, or subscribing to a massive collection
        // we perform search on the server which will return array of {label: 'One', value: 1} 
        Meteor.call('massiveCollectionSearch', request.term, function(err,res){
          if(err) {
            console.error(err);
          } else {
            if(res.length > 0)
              callback( res );
          }
        });
      },
      focus: function() {
        // prevent adding the value on focus
        return false;
      },
      select: function( event, ui ) {
        this.value = ui.item.label;
      }
    })
    .on('keydown', function(event, ui){
      if(event.keyCode == 13)
      {
        // prevent form submission
        event.preventDefault();
        // close the autocomplete
        $autocomplete.autocomplete('close');
        // store the selected value
        Session.set('massiveCollectionTypeahead',this.value);
      }
    })
    .on('autocompleteselect', function(e,ui){
      e.preventDefault();
      if(ui)
      {
        Session.set('massiveCollectionTypeahead',ui.item.value);
      }
      // return false;
    })
    ;
  });
}

if(Meteor.isServer) {
  Meteor.methods({
    'massiveCollectionSearch'(search) {
      var searchRegEx = new RegExp(RegExp.escape(search),'i');
      var res = [];
      MassiveCollection.find({name: searchRegEx}).forEach(function(item){
        res.push({label: item.name, value: item._id});
      });
      return res;
    }
  });
}

#6

Thanks a bundle, I’ll try this out


#7

For the server method I replaced MassiveCollection with TickerList (the db with the tickers), but the search box is unreactive to any input.

Meteor.methods({ 'massiveCollectionSearch'(search) { var searchRegEx = new RegExp(RegExp.escape(search),'i'); var res = []; TickerList.find({name: searchRegEx}).forEach(function(item){ res.push({label: item.name, value: item._id}); }); return res; } });


#8

Check your browser console for errors. Did you add jQuery UI to your app?