user1063287
user1063287

Reputation: 10869

How to replace prefetch source in Bloodhound with a 'real time' alternative?

I've been using Bloodhound with the prefetch [docs] option defined.

This works fine, except when I add content to the json file being prefetched, it is not available as a search result unless I restart the browser.

So I am trying to make the search results reflect the updated file content in 'real time'.

I tried simply replacing prefetch with remote but this causes the search functionality not to work as intended (it shows non-matched results).

Below is the code I am using with prefetch.

Version info: typeahead.bundle.min.js at v0.10.5.

function searchFunction() {
    var template =
        "<p class=\"class_one\">{{area}}</p><p class=\"class_two\">{{title}}</p><p class=\"class_three\">{{description}}</p>";
    var compiled_template = Hogan.compile(template);
    var dataSource = new Bloodhound({
        datumTokenizer: function(d) {
            return Bloodhound.tokenizers.whitespace(d.tokens.join(
                ' '));
        },
        queryTokenizer: Bloodhound.tokenizers.whitespace,
        prefetch: '/static/my_file.json'
        # remote: '/search'
    });
    dataSource.initialize();
    $('.my_lookup .typeahead').typeahead({}, {
        source: dataSource.ttAdapter(),
        name: 'courses',
        displayKey: 'title',
        templates: {
            suggestion: compiled_template.render.bind(
                compiled_template)
        }
    }).focus().on('typeahead:selected', function(event, selection) {
        var title = selection.title
            // do things with the title variable
    });
}

Edit:

I started thinking perhaps I need some server side logic to perform a search on a database that contains the content previously within the local json file.

Using the code posted below, the following works:

The following does not work:

And, the results from the database are in the following format, and I don't know how to apply the Hogan template for the suggestions to each result:

{
    "matches": [{
        "tokens": ["apple", "orange"],
        "area": "Nautical",
        "_id": {
            "$oid": "4793765242f9d1337be3d538"
        },
        "title": "Boats",
        "description": "Here is a description"
    }, {
        "tokens": ["apple", "pineapple"],
        "area": "Aviation",
        "_id": {
            "$oid": "4793765242f9d1337be3d539"
        },
        "title": "Planes",
        "description": "Here is a description."
    }]
}

JS

function searchFunction() {

var engine = new Bloodhound({
    remote: {
        url: '/search?q=%QUERY%',
        wildcard: '%QUERY%'
    },
  datumTokenizer: Bloodhound.tokenizers.whitespace('q'),
  queryTokenizer: Bloodhound.tokenizers.whitespace,

});

engine.initialize();

$('.my_lookup .typeahead').typeahead({
}, {
source: engine.ttAdapter(),
name: 'courses',
displayKey: 'title',
templates: {
suggestion: function (data) {
                return "// not sure how to apply markup to each match"
      }
}
}).focus().on('typeahead:selected', function(event, selection) { 
console.log(selection);
var title = "// again not sure how to access individual match data"
// do things with the title variable
});
}

MongoDB Schema

Database: courses
Collection: courses
Documents:

{
    "_id" : ObjectId("4793765242f9d1337be3d538"),
    "tokens" : [ 
        "apple", 
        "orange"
    ],
    "area" : "Nautical",
    "title" : "Boats",
    "description" : "Here is a description."
}

and:

{
    "_id" : ObjectId("4793765242f9d1337be3d539"),
    "tokens" : [ 
        "apple", 
        "pineapple"
    ],
    "area" : "Aviation",
    "title" : "Planes",
    "description" : "Here is a description."
}

etc

Python (using Bottle routes)

@route('/search')
def search():
    """
    Query courses database for matches in tokens field.    
    """
    # get the query
    query  = request.GET.q
    # define the database
    dbname = 'courses'
    db = connection[dbname]
    # define the collection
    collection = db.courses
    # make the query
    matches = collection.find({"tokens":query})
    # send back results
    results = {}
    results['matches'] = matches
    response.content_type = 'application/json'
    return dumps(results)

Upvotes: 4

Views: 547

Answers (0)

Related Questions