meteor-autocomplete
meteor-autocomplete copied to clipboard
Support lookup in multiple fields per collection
Why can't you just do this with different tokens? Are you saying you want to use the same token to search in different fields (and possibly in different collections?)
I want to search for the input string in two fields of the same collection, the Name and the Symbol of a company. I don't want to use a token at all actually (see issue #4) but for now I'll settle for ' '.
The selector field can now be used in a rule to generate a custom selector for the autocomplete search selector. Does this sufficiently allow what you want to do?
So currently I am trying to get the following effect. In my autocomplete I want to drill down based on either the profile.display_name or profile.login.When a user wants to complete the autocomplete, I would like for the autocomplete to complete to the profile.login
The only thing I have working, which is the simple part of this setup is that the template shows the profile.display_name.
This is what I have tried so far and will continue to work on this, but I could use some help.
Template.autocomplete.settings = () ->
return {
position: "top",
limit: 10,
rules: [
token: '@',
collection: Meteor.users,
field: "profile.display_name",
template: Template.getUsers,
selector: (match) ->
return Meteor.users.find({$or: [{'profile.display_name': match}, {'profile.login': match}]})
]
}
@kfollmer instead of returning a cursor for selector, just use the { $or: ... } part. You may also want to do something like regex = new RegExp(match, "i") and pass that in to the selector, if you want to do partial matches and not be case-sensitive either.
@mizzao Do you mean setting up something like this for the field?
field: {$or: {'profile.display_name'}, {'profile.login'}}
Im not quite sure where to use the { $or: ... } and how to use it properly
No, I think you should just do
selector: (match) ->
regex = new RegExp(match, 'i')
return {$or: [{'profile.display_name': regex}, {'profile.login': regex}]}
Does that work?
Yeah that worked! I'm 95% of the way there, just one last thing.
Currently I am getting my display_name as a user's full name (i.e. John Doe), and as it is now the autocomplete just stops working when you type a space.
For example: If I typed @John and then left the menu up, and there just so happened to be more than one John, is there a way to keep the autocomplete up when I type a space? That would be awesome.
Thanks for the help
Currently, not unless you use the whole field as the autocomplete, because we can't tell apart spaces in selected items from other word boundaries.
You could modify it yourself in https://github.com/mizzao/meteor-autocomplete/blob/master/autocomplete-client.coffee#L12. I have thought about this a little but I'm not sure what a good way it is to support it without either making it the entire field or just whitespace-separated.
Okay, that's no problem.
Thanks for all the help.
If you ever get around to doing it or having an update that works around that, if you could send me a message on here so I get notified that would be awesome.
Thanks again
Just pushed multi-field autocomplete in production for StockBase - thanks @mizzao.
Two minor issues:
- The docs (here and code (my last code commit, and here) assume in places that there's only one field to match against. Does this need updating in light of multiple-field selectors?
- The autocomplete template may need to be customized according to what field had matched. How could I pass the match suffix to the template, or fetch it from there, the way it's passed to the
selectorfunction?
Re. this comment, I found that { symbol: new RegExp(match, 'i') } was received by the server as symbol: {}. Can RegExp's be serialized correctly?
@dandv not sure how you implemented multi-field autocomplete. Did you just make multiple rules with the same symbol? Or are you using an $or selector?
Answers to your questions:
- If you use
$orin the selector, you probably want to just fill in one thing forrule.field- so you would probably pick the stock symbol or whatever the canonical representation is. - Maybe we could make template take a function as well and pass in the match, in addition to a constant template.
Regarding your second post, use { symbol: { $regex: match, $options: 'i' } }
$or selector:
var orSearch = [
{ symbol: { $regex: match.toUpperCase().regexEscape() } }, // symbols are always uppercase
{ name: { $regex: match.regexEscape(), $options: 'i' } }
];
A polymorphic signature for the template would be great (taking a function as well as a template object).
How many companies are in your DB? Isn't that query going to eat CPU since it's matching in the middle of the string?
To take advantage of indexes, consider making a lowercase key for each company name (as well as the uppercase symbol), and sending a lowercase regex match starting with ^ in the query.
About 20k companies. No performance issues so far, but a secondary key is a good suggestion to have in mind.