Closed yanndebelgique closed 10 years ago
I think if we can index multiple collections and use the resultset
to search off of, then there might be minimal changes to make this work
But that would mean that you'd get 2 different sets of data back, and you'd have to filter out if the doc is from either of the several collections you specified.
I'd make the collection a possible array field, eg:
EasySearch.createSearchIndex('mixedSearch', {
'collection' : [Cars, Fruits, Roles], // instanceof Meteor.Collection
'fields' : ['name', 'price']
});
Price wouldn't be a field in the Roles collection which means inconsistent data. Did you have that in mind? If not, what would you like? I see that having a facet search over several collections would be nice. B eing able to define the 'es' fields which are being indexed would be another option.
Yes I would specify for each collection the fields to search over. I don't think that would be redundant.
In a webapp you want one general search bar that searches all collections. Today's internet user is used to the google search bar that looks across multiple types of docs.
sorry for the late reply.
@matteodem I like that approach of identifying the collection as an option when making the index. I think it would be nice to filter out inconsistent data at runtime and let the user make that decision.
How would you filter out inconsistent data? I'd probably split up the results by collection (index).
@matteodem Yea as long as the index is tagged with which collection, then I can get the information returned based on each index. Will this cause problems ?
It's not problematic, but it'll most probably need some overhaul of the current logic. I'll start in the next weeks with it.
I implemented it with a rather simple approach, please give me feedback and re-open if you miss anything https://github.com/matteodem/meteor-easy-search#searching-over-several-collections.
I would like to use it via Blaze Components, but i'm not sure i fully understand that documentation :
"If you want to use it with the Blaze Components, you can simply change the index parameter to an array and define one esEach loop for each index defined."
Can you please provide an exemple of how and where to declare things to make it work ?
Thanks
Added an example to the REAME.md which looks like this:
<div class="search-input">
<!-- indexes is a javascript array which holds 'players' and 'cars' -->
{{> esInput index=indexes placeholder="Search..." }}
</div>
<div class="results-wrapper">
{{#esEach index="players"}}
{{> player}}
{{/esEach}}
{{#esEach index="cars"}}
{{> car}}
{{/esEach}}
</div>
For further clarification, you'd have to declare the variable like this:
Template.yourTemplate.indexes = ['players', 'cars'];
Thanks a lot ! ;)
I am also trying to use Blaze Components for multi-collection searching (e.g., dogs, cats and birds). I have created the search index for each collection separately, each having multiple fields, and searching each collection separately works well. I am using those same individual search indices for the multi-collection searching according to @matteodem 's example code two posts above. It doesn't show any results when I am searching. Should I not use the same search indices and create a new one? If so, how do I create a search index for multi-collection? Thanks!
@artitw It doesn't work at the moment and there's a bug #72. I'll have a look this week
Thank you, @matteodem ! Great stuff so far. Multi-collection search would be beyond awesome. I really look forward to it.
It worked at some time, bugs me that it doesn't anymore. A CI would be great but I'll have to find the time for it. Thanks!
hi, is the code example you posted above still the best way to do this? I am trying to search over 2 collections using elastic search.
yep should work, this is also useable in the easy-search-leaderboard example.
Hi @matteodem! My table contains multiple fields of multiple collections through some helpers. I don't want to separate search results by index, but each table row must contains all collections fields. Can I do it?
Hello @alearcy What do you mean? You can create an index for each collection and pass in an array of indexes for the search. I'll add a Recipe section about it, if that could help you.
@matteodem I can't find docs about search in multiple collections anymore, is it added somewhere?
I already found examples how to do that in this issue but think, that example must be added into documentation.
http://matteodem.github.io/meteor-easy-search/docs/blaze-components/, see "Components with multiple indexes"
The above link results in a 404. What is the current status on search across multiple indexes?
Please have a closer look at the docs, components here show that some accept multiple indexes http://matteodem.github.io/meteor-easy-search/docs/components/ and with the new API in v2 you can search through multiple indexes by using the search
method on all the indexes you want to search.
I saw that part of the doc. That gives me the answer to my question, indeed.
Is there any documentation on how to implement it? I tried earlier following the above example (index=indexes
, declaring indexes in the template helper), but got errors about no index or array of indexes being passed on (if I recall correctly).
For the record: It seems to me that the above examples are outdated in terms of syntax by now (got a warning when trying to use Template.yourTemplate.indexes = ['players', 'cars'];"
, suggesting to set this up in the template helper).
Yes they are, because they refer to the v1 API. It should be indexes=indexes
if you want to use multiple indexes. I'll add a new section about searching with multiple indexes
on the components page.
I get the following error when trying to search on multiple indexes:
Error: Did not receive an index or an array of indexes: "[object Object],[object Object]" [invalid-configuration]
I am trying with this code:
MyTemplate.html
{{> EasySearch.Input index=indexes }}
MyTemplate.js
Template.MyTemplateName.helpers({
indexes: () => [firstIndex, secondIndex]
});
Both indexes are declared via new EasySearch.Index()
.
What is it I'm missing/doing wrong?
The parameters should be indexes
instead of index
on your input.
{{> EasySearch.Input indexes=indexes }}
I don't quite get what you are hinting at, sorry.
Assuming I have:
firstIndex = new EasySearch.Index({
collection: FirstCollection,
fields: ['field1', 'field2'],
engine: new EasySearch.MongoDB()
});
and
secondIndex = new EasySearch.Index({
collection: SecondCollection,
fields: ['field1', 'field2'],
engine: new EasySearch.MongoDB()
});
What should my template and my helpers look like?
I also can't get search over multiple indexes to work, and would be very grateful if you can explain what I need to do. I'm using this in my template:
{{> EasySearch.Input indexes=indexes attributes=attributes }}
I get this error on the client: "Error: Can only specify one index [only-single-index]"
The rest of my code is:
client and server:
PatternsIndex = new EasySearch.Index({
collection: Patterns,
fields: ['name', 'tags'],
engine: new EasySearch.Minimongo(),
defaultSearchOptions: {
limit: 8
}
});
ColorsIndex = new EasySearch.Index({
collection: Colors,
fields: ['name'],
engine: new EasySearch.Minimongo(),
defaultSearchOptions: {
limit: 8
}
});
and client only: Template.search.indexes = [PatternsIndex, ColorsIndex];
FYI, I also tried assigning a name to each Index like this:
PatternsIndex = new EasySearch.Index({
name: 'patternsIndex',
collection: Patterns,
fields: ['name', 'tags'],
engine: new EasySearch.Minimongo(),
defaultSearchOptions: {
limit: 8
}
});
and changing my helper to this:
Template.search.indexes = ["patternsIndex", "testIndex"];
But I get the error "Error: Did not receive an index or an array of indexes: "patternsIndex,testIndex" [invalid-configuration]"
Easy Search is an awesome package and I'd really like to get this working!
firstIndex = new EasySearch.Index({
collection: FirstCollection,
fields: ['field1', 'field2'],
engine: new EasySearch.MongoDB()
});
secondIndex = new EasySearch.Index({
collection: SecondCollection,
fields: ['field1', 'field2'],
engine: new EasySearch.MongoDB()
});
Template.myTemplate.helpers({
indexes: function () {
return [firstIndex, secondIndex];
},
firstIndex: function () {
return firstIndex;
},
secondIndex: function () {
return secondIndex;
}
});
<template name="myTemplate">
{{> EasySearch.Input indexes=indexes}}
{{#EasySearch.Each index=firstIndex}}
...
{{/EasySearch.Each}}
{{#EasySearch.Each index=secondIndex}}
...
{{/EasySearch.Each}}
</template>
Having the above in the docs would be super helpful, got it working but the syntax is easy to get wrong.. thanks for this - the example you posted is great.
you're right. I'll add an issue for that
Thank you! I agree the syntax is tricky - I could only get it to work by copying your example and then changing one name at a time, but it is now working, awesome!
Is there any way to do IfSearching, IfNoResults across multiple indexes? Or do I need to construct nested statements in my template?
How will LoadMore work with multiple indexes? I don't want multiple buttons...
please create new issues for these questions.
Thank you. I've created three new issues:
Just a quick comment for anyone viewing this. There is a typo in @matteodem code example.
{{/EasySarch.Each}}
instead of
{{/EasySearch.Each}}
just missing an "e"
thanks, changed it.
added examples for multiple indexes here http://matteodem.github.io/meteor-easy-search/docs/components/ (Using multiple indexes)
It's not working for me though i followed the documentation step by step. Here are my configurations (sorry for the very long post, but to make everything clear):-
Indexes
ProductsIndex = new Index({
collection: Products,
fields: ['name', 'brand', 'category'],
engine: new EasySearch.MongoDB({
transform(doc){
try{
let imageFile = Images.findOne({_id: doc.picture});
doc.imageFile = imageFile;
return doc;
}
catch(ex){
console.log(ex);
return doc;
}
}
}),
defaultSearchOptions: {
limit: 25
}
});
CategoriesIndex = new Index({
collection: Categories,
fields: ['name'],
engine: new EasySearch.MongoDB(),
defaultSearchOptions: {
limit: 25
}
});
JS
Template.MyTemplate.helpers({
productsIndex: function(){
return ProductsIndex;
},
categoriesIndex: function(){
return CategoriesIndex;
},
searchIndexes: function(){
return [ProductsIndex, CategoriesIndex];
},
searchInputAtts: {
class: 'form-control search-input',
placeholder: (Session.get('lang') == 'ar')? 'بحث...' : 'Search...'
},
loadMoreAtts: {
class: 'btn load-more-btn'
},
loadMoreContent: function(){
/*return '<i class="fa fa-spinner"></i> ' +
'<span>' +
((Session.get('lang') == 'ar')? 'المزيد...' : 'More...') +
'</span>';*/
return 'More...';
},
empty_text: () => {
return (Session.get('lang') == 'ar')? 'أدخل كلمات للبحث...' : 'Enter search text...';
},
no_result_text: () => {
return (Session.get('lang') == 'ar')? 'لا توجد نتائج للبحث...' : 'No matches...';
},
searching_text: () => {
return (Session.get('lang') == 'ar')? 'جاري البحث...' : 'Searching...';
},
notInSearchRoute: () => {
return !Session.get('inSearch');
}
});
HTML
<template name="MyTemplate">
{#if Template.subscriptionsReady}}
<div class="form-group search-form">
{{> EasySearch.Input indexes=searchIndexes attributes=searchInputAtts }}
{{#if notInSearchRoute}}
{{#EasySearch.IfInputEmpty indexes=searchIndexes}}
<div class="no-results">{{empty_text}}</div>
{{else}}
{{#EasySearch.IfNoResults indexes=searchIndexes logic="AND" }}
<div class="no-results">searchIndexes {{no_result_text}}</div>
{{else}}
{{#EasySearch.IfNoResults index=productsIndex}}
<div class="no-results">productsIndex {{no_result_text}}</div>
{{/EasySearch.IfNoResults}}
<ul class="quick-search-list">
{{#EasySearch.Each index=productsIndex}}
...
</div>
{{/if}}
</template>
Now the only result i get is: searchIndexes No Matches... no matter the query is.
PS: it used to work with one index smoothly
PS2: When I try from chrome devTools console, this is what I get (first time no results, second time has results):-
ProductsIndex.search('a');
>Cursor {_mongoCursor: L…n.Cursor, _count: 0, _isReady: false, _publishHandle: null}
ProductsIndex.search('a');
>Cursor {_mongoCursor: L…n.Cursor, _count: 8, _isReady: true, _publishHandle: Object}
CategoriesIndex.search('a');
>Cursor {_mongoCursor: L…n.Cursor, _count: 0, _isReady: false, _publishHandle: null}
CategoriesIndex.search('a');
>Cursor {_mongoCursor: L…n.Cursor, _count: 2, _isReady: true, _publishHandle: Object}
Please advise...
Man that would be sweet. Is that in the pipeline?