a-ok Posted June 9, 2020 Share Posted June 9, 2020 I'm a bit stuck with this search result setup. $fieldsToSearch = 'title|text|textA|textarea|projectsCategories.title|projectsClients.title|aboutPressCategories.title|aboutPressClients.title'; $templatesToSearch = 'projectsSingle|shopSingle|typeSingle|typeCustomSingle|typeCustomSingleB|aboutPressSingle|repeater_modulesA'; $results = $pages->find("$fieldsToSearch%=$searchQuery, template=$templatesToSearch, sort=sort, check_access=0"); It should search all those templates (including the repeater). If the result is a repeater then it returns the `getForPage()` foreach ($results as $result) { if ($result->template->name == 'repeater_modulesA') $result = $result->getForPage(); } This is pretty straightforward. I just have an issue... 1. If the getForPage() is in the trash it's still getting returned (it shouldn't) but I guess that's because the repeater isn't in the trash. Is there anything I can apply to the selector to avoid this? Or before I loop through $results should I do a check to remove any $result where status is trash? $results = $pages->find("$fieldsToSearch%=$searchQuery, template=$templatesToSearch, sort=sort, check_access=0"); $results = $results->not("status<" . Page::statusTrash); Thoughts? I guess the issue with the above is that it'll be checking the repeater for trash, not the getForPage(). Link to comment Share on other sites More sharing options...
a-ok Posted June 9, 2020 Author Share Posted June 9, 2020 $results = $pages->find("$fieldsToSearch%=$searchQuery, template=$templatesToSearch, sort=sort, check_access=0"); $resultsToRemove = new PageArray(); foreach ($results as $result) { if ($result->template->name == 'repeater_modulesA' && ($result->getForPage()->is('unpublished') || $result->getForPage()->is('trash'))) { $resultsToRemove->add($result); } } $results = $results->not($resultsToRemove); I had to end up doing the above. Maybe this is correct but seems a bit crazy. Link to comment Share on other sites More sharing options...
Robin S Posted June 9, 2020 Share Posted June 9, 2020 The normal way to match content in a Repeater is by searching the subfields of the Repeater. Instead of... my_field%=foo, template=repeater_my_repeater_field ...you would do... my_repeater_field.my_field%=foo That way you are matching the pages that contain the repeater field so you don't need getForPage(), plus you don't have to deal with the access restrictions on the Repeater template, unpublished repeater items, sorting of the container pages, etc. 10 hours ago, a-ok said: $fieldsToSearch = 'title|text|textA|textarea|projectsCategories.title|projectsClients.title|aboutPressCategories.title|aboutPressClients.title'; Have you considered merging the text of all the fields you want to search into a hidden "index" textarea field? It's not too difficult to do this with a Pages::saveReady hook, but to make it really easy you can use the SearchEngine module which takes this approach. Doing this has the potential to solve the other issues you raised here and here (you could strip apostrophes from text that is saved to the index field). 1 Link to comment Share on other sites More sharing options...
a-ok Posted June 10, 2020 Author Share Posted June 10, 2020 14 hours ago, Robin S said: That way you are matching the pages that contain the repeater field so you don't need getForPage(), plus you don't have to deal with the access restrictions on the Repeater template, unpublished repeater items, sorting of the container pages, etc. Of course! That makes perfect sense. Doh. Your method of merging all the relevant text to one field makes sense, also. Thanks and nice work! The only issue is if someone searched 'Kettle's' it wouldn't return, would it, as the text it's returning doesn't have the apostrophe? Also, while I'm on the subject, has anyone attempted to implement a fuzzy search with PW? Link to comment Share on other sites More sharing options...
Robin S Posted June 10, 2020 Share Posted June 10, 2020 9 hours ago, a-ok said: The only issue is if someone searched 'Kettle's' it wouldn't return, would it, as the text it's returning doesn't have the apostrophe? You would strip apostrophes from the search input also. The general idea is you strip out any characters that shouldn't affect the search from both the input and the stored index. 9 hours ago, a-ok said: Also, while I'm on the subject, has anyone attempted to implement a fuzzy search with PW? There is discussion in this topic: On one site I've implemented a fuzzy search that uses the Levenshtein distance with the approach described here, but it was done with plain SQL and searched only the title field. Using it on multiple fields has the potential to generate a huge number of queries so performance could become an issue. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now