filterByKeywords cannot search against multiple keywords
Permalink
I'm using the function filterByKeywords, and it seems to only do exact string matches.
This seems to be the case when filtering a PageList object as well as FileList objects.
I need to be able to take a string of keywords, and filter the list per word, rather than against the whole string.
For example, both of the below searches should ideally return the same result:
"example search"
"search example"
I've seen solutions elsewhere that suggest exploding the keywords string into an array using space as a delimiter. Then loop through the array and call filterByKeywords per keyword.
However, that doesn't work. The search just ends up using the last word in the array and none of the others.
This also seems to be the way that the search block is currently working.
I'm working on 5.7.5.13.
This seems to be the case when filtering a PageList object as well as FileList objects.
I need to be able to take a string of keywords, and filter the list per word, rather than against the whole string.
For example, both of the below searches should ideally return the same result:
"example search"
"search example"
I've seen solutions elsewhere that suggest exploding the keywords string into an array using space as a delimiter. Then loop through the array and call filterByKeywords per keyword.
However, that doesn't work. The search just ends up using the last word in the array and none of the others.
This also seems to be the way that the search block is currently working.
I'm working on 5.7.5.13.
You should be able to do something like this
Sorry, just re-read what you asked for and this will not do it, this will only search the words in order (with other stuff in between).
I found a way of doing it.
Rather than make an array and call the function per word, I changed the function itself to create and use an exploded array.
I made the following changes:
In \concrete\src\File\FileList.php, I changed this:
To this:
Then in \concrete\src\Attribute\Controller.php, I changed this:
To this:
Rather than make an array and call the function per word, I changed the function itself to create and use an exploded array.
I made the following changes:
In \concrete\src\File\FileList.php, I changed this:
public function filterByKeywords($keywords) { $expressions = array( $this->query->expr()->like('fv.fvFilename', ':keywords'), $this->query->expr()->like('fv.fvDescription', ':keywords'), $this->query->expr()->like('fv.fvTitle', ':keywords'), $this->query->expr()->like('fv.fvTags', ':keywords'), $this->query->expr()->eq('uName', ':keywords') ); $keys = FileAttributeKey::getSearchableIndexedList(); foreach ($keys as $ak) { $cnt = $ak->getController(); $expressions[] = $cnt->searchKeywords($keywords, $this->query); } $expr = $this->query->expr();
Viewing 15 lines of 18 lines. View entire code block.
To this:
public function filterByKeywords($keywords) { $keywords = explode(' ', $keywords); foreach($keywords as $key => $word) { $expressions = array( $this->query->expr()->like('fv.fvFilename', ':keywords_'.$key), $this->query->expr()->like('fv.fvDescription', ':keywords_'.$key), $this->query->expr()->like('fv.fvTitle', ':keywords_'.$key), $this->query->expr()->like('fv.fvTags', ':keywords_'.$key), $this->query->expr()->eq('uName', ':keywords_'.$key) ); $keys = FileAttributeKey::getSearchableIndexedList(); foreach ($keys as $ak) { $cnt = $ak->getController(); $expressions[] = $cnt->searchKeywords($word, $this->query, ':keywords_'.$key);
Viewing 15 lines of 21 lines. View entire code block.
Then in \concrete\src\Attribute\Controller.php, I changed this:
public function searchKeywords($keywords, $queryBuilder) { return $queryBuilder->expr()->like('ak_' . $this->attributeKey->getAttributeKeyHandle(), ':keywords'); }
To this:
public function searchKeywords($keywords, $queryBuilder, $keywords = ':keywords') { return $queryBuilder->expr()->like('ak_' . $this->attributeKey->getAttributeKeyHandle(), $keywords); }
Another way to do this is to subclass PageList to provide a new function (say, filterByKeywordsBoolean) that uses MySql's 'IN BOOLEAN MODE' modifier.
If anyone wants to test or dissect a rough search block that can search for multiple keywords, try the attached.