olivernn / lunr.js

A bit like Solr, but much smaller and not as bright
http://lunrjs.com
MIT License
8.91k stars 547 forks source link

Example use for lunr.Index.query()? #261

Closed nikolas closed 6 years ago

nikolas commented 7 years ago

The documentation here is helpful:

https://lunrjs.com/docs/lunr.Index.html#query

But I would like to add an example on how to use this method for an example QueryString, for example, *apple* color:red.

olivernn commented 7 years ago

The interface for lunr.Query is fairly basic, I sort of deliberately have not added much in the way of sugar for creating queries programatically, instead waiting to see if any patterns do fall out of general use.

Specifically, for the query you mention, it could be expressed like this:

var fruit = "apple", colour = "red"

idx.query(function (q) {
  q.term("*" + fruit + "*")
  q.term(colour, { fields: ["color"] })
})

As you can see, there is currently no nice way of adding wildcards, instead you have to do the string concatenation yourself. This is something that I want to improve, perhaps having a property with some flags:

q.term(fruit, { wildcard: lunr.Query.Wildcard.LEADING | lunr.Query.Wildcard.TRAILING })

That said, I'm not usually a big fan of having a large list of options, it's too easy to make mistakes, so perhaps some kind of builder:

q.term(fruit, function (t) {
  t.wildcard(LEADING | TRAILING)
  t.fields('name', 'description')
  t.boost(10)
})
olivernn commented 7 years ago

So I put together a change to see how the wildcarding would look, let me know any feedback.

nikolas commented 7 years ago

Great, thanks a lot for these examples. I have a search form that takes a text input, which I'm using the wildcard for, plus a few dropdown menus for faceted search. I'm joining together the facets like this:

results = index.query(function(q) {
    q.term(mainTerm);
    searchParams.forEach(function(param) {
        var k = param[0];
        var v = param[1];
        q.term(v, { fields: [k] });
    });
});

lunr.js joins these terms using OR instead of AND. Is there a way to use AND instead of OR, or is that not implemented in lunr.js yet?

olivernn commented 7 years ago

AND is not implemented yet, though its definitely on something I want to add. The implementation isn't so much the problem, rather the query interface, if you have any suggestions on what the API would look like I'd be interested to hear them.

Please open a new issue requesting AND search, I'll keep this one open just to remind me to improve the documentation around the programatic query API.

olivernn commented 6 years ago

As of 2.2.0 term presence is supported by Lunr. The interface isn't exactly "foo AND bar", rather the presence of each term can be specified. By default each term is optional, which gives you "foo OR bar". To get "foo AND bar" would be +foo +bar, i.e. documents must contain foo and must contain bar.

I'll update the docs/guides shortly with more examples.