My current Sphinx configurations only returns results matching the whole words, but i would like sphinx to return search for parts of word too.
e.g.
if i search for word
block
it should return result containng all words whic contains word block and not just exat matches.
e.g.
blockbuster
megablockbuster
megablock
its simillar to using block in query
my current SPhinxQL query looks like this
SELECT id FROM disk_index1 WHERE MATCH('block') LIMIT 0,25 OPTION max_matches = 10000
i have tried answer from
ref: searching in a part of word with Sphinx
enable_star=1
but
its depreciated now.
i have even tried running query like this
SELECT id FROM disk_index1 WHERE MATCH('*block*') LIMIT 0,25 OPTION max_matches = 10000
but still it doesnt returns partial words matches
How can i enable partial word matches ? in SPhinxQL ?
Sphinx Server version: 2.2.9-id64-release (rel22-r5006)
on Cent Os 7 x 64
my current index configuration has
docinfo = extern
morphology = stem_en
enable_star = 1
You can use min_infix_len and min_prefix_len to achieve this:
Infix length setting enables wildcard searches with term patterns like
'start*', '*end', '*middle*', and so on. It also lets you disable too
short wildcards if those are too expensive to search for.
Read more on Sphinx Search current documentation.
Related
I am using MySql FullText indexing to search data from database.
Here is the query
$search_input_text = 'the_string_to_be_search';
$searchArray = explode(" ", $search_input_text);
$query="SELECT * FROM car_details
WHERE MATCH (car_trim) AGAINST ('";
foreach ($searchArray as $word) {
$query .= "+".$word."* ";
}
$query .= "' IN BOOLEAN MODE) LIMIT $start, $limit";
The query is executing fine but it has a bug, if you look at the column name you will find car_trim which is inside the MATCH() function. The column has only 3 different types of values in the database which are 'T5', 'T6' and 'T5 premier'.
When I type 'Premier' in the search bar and hit Enter, it fetches the results whose values contain the word 'Premier'. But when I type T5 or T6 , it returns an empty record. Please be sure that there are lots of records with car_trim='T5', car_trim='T6' or car_trim='T5 Premier'
I am not getting that what can be the problem with the strings T5 and T6.
MySQL has two key parameters when using full text search (and a few other important ones). The key parameters are the minimum word length and the stop words list. In short, MySQL ignores words that are less than 3 or 4 characters (depending on the storage engine) or that are in the stop word list.
Your examples ("T5" and "T6") are too short -- based on the parameter defaults.
Some other configuration parameters might be of interest, such as the maximum word length and the characters that are valid for words.
You can change the parameters for full text indexing and re-build the index.
Here is a good place to start in understanding this.
I'm using Sphinx to provide a search webpage to a huge set of data, recently I upgraded Sphinx from v2.1.8 to v2.2.4
I had some troubles in config file, one of them is that 'enable_star' option has been removed, which affected the expected results in my search page, so if search for 'rea' it will not return 'real madrid' until I complete typing 'real', the same issue at words ends 'madrid'.
The expected results if I searched for 'mad' :
Real Madrid
Atlatico Madrid
Mad-Croc
Madila
mad bla
In my case I get 'Mad-Croc' and 'mad bla'.
Here is a part of my config file :
docinfo = extern
mlock = 0
morphology = stem_en
min_word_len = 1
expand_keywords = 1
dict = keywords
PHP Code :
$_sphinx = new SphinxClient();
$_sphinx->SetServer('............', '....');
$_sphinx->SetMatchMode(SPH_MATCH_ANY);
$_sphinx->SetFieldWeights(array('auther_name' => 50));
$_sphinx->SetArrayResult(true);
$_sphinx->SetSortMode(SPH_SORT_EXTENDED2, 'cat_priority DESC, #weight DESC');
//////////////////
$_result = $_sphinx->Query($searchTerm . '*');
could any body look for this.
You dont seem to have min_prefix_len setup on your index, suggest you add it.
Although not sure how your index would ever of worked, as min_prefix_len, would be required for enable_star=0 to have an effect.
That should allow expand_keywords to work its magic. At which poing suggest removing the * from the end of the query. Which would only affect the last word entered anyway, and * should autotmatically by added by expand_keywords setting anyway.
How can i find similar word in sql? for example:
i have those words -
hell, llo, hl, lh
I want to find the matching word to "hello" or "helloworld"
And the order will be by most matching letters
i tried to do with "LIKE" but it limited results
You may have some luck with fulltext indexes
I think you are looking for something like this:
SELECT words.*
FROM words
WHERE 'hello' LIKE CONCAT('%', word, '%')
ORDER BY
LENGTH(word) DESC
Please see fiddle here. Please notice that this query won't be very fast, as it can't make use of an index.
Try using the LOCATE function, which returns the first character position when it finds a needle in a haystack. You could do that for each of your terms with an IF > 0 THEN...:
SELECT * FROM tablename
ORDER BY
(
IF(LOCATE('hell', field_to_search) > 0, 1, 0)
+ IF(LOCATE('llo', field_to_search) > 0, 1, 0)
+ IF(LOCATE('hl', field_to_search) > 0, 1, 0)
+ IF(LOCATE('lh', field_to_search) > 0, 1, 0)
) DESC
If field_to_search contains (case insensitively) all four terms, it will have 4 in that order by field, and zero if it doesn't match any etc. This won't limit your results like WHERE field_to_search LIKE '%hell%' etc.
Using the IF(LOCATE structure will also allow you to give different weighting to different search terms, e.g. if it matches hell you might give it 4 points, llo might give it 3. So it could theoretically match hl and lh but not hell or llo and still come up above a term that matches the top two (if you weight the bottom two higher than the top etc).
Documentation: http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_locate
I have a problem. I made a simple search engine which searches by brand and model of car. For reasons of query performance and a lot of data in database, I decided to use full-text search. It's ok, but now I come across the problem:
I would like to find all cars with brand "Audi" and with model "Q7". For now, I have this SQL query, but it doesn't work right, because of word length "Q7":
SELECT `a`.`id`, `a`.`title`, `a`.`askprice`, `a`.`description`, `a`.`picture`
FROM (`mm_ads` as a)
WHERE `a`.`category` = '227'
AND `a`.`askprice` >= '0'
AND `a`.`askprice` <= '144000'
AND (MATCH(a.title) AGAINST ('+audi +q7' IN BOOLEAN MODE ))
GROUP BY `a`.`id`
ORDER BY `a`.`id` ASC
LIMIT 30
I don't have access to modify MySQL config file, to set ft_min_word_len to value 2. For now value is 3. Is there any other way to deal with that?
Here is another problem:
I would like to get all cars brand "BMW" and model "116". For example, I have a car named BMW, 1, 116i. My SQL query is:
`SELECT `a`.`id`, `a`.`title`, `a`.`askprice`, `a`.`description`, `a`.`picture`
FROM (`mm_ads` as a)
WHERE `a`.`category` = '227'
AND `a`.`askprice` >= '0'
AND `a`.`askprice` <= '144000'
AND (MATCH(a.title) AGAINST ('+bmw +116' IN BOOLEAN MODE))
GROUP BY `a`.`id`
ORDER BY `a`.`id` ASC
LIMIT 30`
Search return 0 rows. Why? All input strings ("BMW", "116") are min length 3. What am I doing wrong?
Regards, Mario
I had a similar issue when dealing with match against (regarding text length) and my answer was to strlen the string first and switch between like and match against for shorter words. Not what I would call graceful, but it was all I could do since I too had no access to the config.
As for the second question, are you sure the default isn't 4? I recall I couldn't search on the term "art" in my case. 3 letters. Had to go with like on everything below 4 chars.
Unless you have access to the config file and can change it I fear there is very little to do.
A change to ft_min_word_len requires a server restart and a full rebuild of the full text index.
As found here
Try this:
for this search: "bmw 116i"
(MATCH(a.title) AGAINST ('+bmw +116i "bmw 116i"' IN BOOLEAN MODE ))
not the best solution but might help...
How I do exact match or anywhere match keywords on the table with php/mysql search engine.
For example: i added a url with keywords: UFC 131 online
And 2nd url with keywords: UFC 132 online
and if i enter UFC 132 on the search box how do i make the 2nd url to come up first?
Because if i use this code
//explode out search term
$search_exploded = explode(" ",$search);
foreach($search_exploded as $search_each)
{
//construct query
$x++;
if ($x==1)
$construct .= "title LIKE '%$search_each%'";
else
$construct .= " or title = '$search'";
and i search for ufc 132 online it gives me ufc 131 online result first.
You could implement something like this:
SELECT *, MATCH (title) AGAINST ('searchstring' IN BOOLEAN MODE) +
CASE
WHEN title = 'searchstring' THEN 10
ELSE 0
END AS relevance FROM `wrestlingsucks`
HAVING relevance > 1.0
ORDER BY relevance DESC LIMIT 100
This is a very basic example, all it will do is add 10 to a sudo relevance column if its an exact match. You could however get as complicated as you want with full text and natural matching.
MySQL has superior search capabilities for full text search than handcrafting your searches. Take a look at fulltext-search
From the documentation MATCH (col1,col2,...) AGAINST (expr [search_modifier])
Use Levenshtein algorithm in MySQL.
Levenshtein matching is a metric for
measuring the amount of difference
between two sequence, here it is
strings. By default MySQL does not
have this function, but you can write
and add one.
Please take a look at the code here and add that code as a system function in MySQL, please see the example below on how to get the similarity of two strings.
Please see: https://github.com/rakesh-sankar/Tools/blob/master/MySQL/Levenshtein.txt
Example: SELECT column1,
LEVENSHTEIN(column1, 'matchme') AS
perfectmatch FROM sometable ORDER BY
perfectmatch DESC