sphinx SQL search: excluding items - php

Have my sphinx search going like so:
$result = $cl->query($_REQUEST['term'], 'myindex');
But I'd like to be able to filter out certain results that don't match a string value, something like:
$result = $cl->query($_REQUEST['term'] . " and somestringcol <> ''", 'myindex');
Is there some proper way to do this using the sphinx PHP API?

You can use SetFilter() to specify a filter on an attribute you defined.
See: http://www.sphinxsearch.com/docs/manual-1.10.html#attributes

As Langdon, metions you can use the SetFilter(), but you may also be able to use the field search operator which is available in the extended search syntax to get a little bit more specific with searching your index rather than attributes associated with it.
$result = $cl->query($_REQUEST['term'] . " #somestringcol -term", 'myindex');
The documentation for sphix provides many good examples: http://sphinxsearch.com/docs/1.10/extended-syntax.html

Related

Search LIKE json object in mysql

Suppose in my sample_table exist field json_field (stringified JSON object, has property_1, property_2)
How can i select like this request: WHERE property_1 LIKE %VALUE_1% AND property_2 LIKE %VALUE_2% without fetching all data and search with php?
P.S. Yes i know, that was mistake to keep json string in field
You can't.
If you want to get data in your script you have to fetch them. Building dynamic request with the arguments.
Something like :
"...WHERE property_1 LIKE '".$value_1."' AND property_2 LIKE '".$value_2.'";
Not familiar with php, however a decent database interface should allow u to execute any select statement. So according to https://dev.mysql.com/doc/refman/8.0/en/create-table-secondary-indexes.html#json-column-indirect-index you should be able to query based on properties inside a JSON type column.
Even using where col->"$.propertyName" = xxx would work.
Using like 'xxx%' prefix search doesn't seem to work correctly though.
But with the page linked above. You should be able to create a generated column on frequently searched field and create index based on it and search like regular column.
basically JSON_EXTRACT() + LIKE + quote() (if you're using PDO) or real_escape_string() (if you're using mysqli)
$db->query("SELECT * FROM sample_table WHERE
JSON_EXTRACT(`json_field`, '$.property_1') LIKE "
. $db->quote("%{$VALUE_1}%").
" AND JSON_EXTRACT(`json_field`, '$.property_2') LIKE "
. $db->quote("%{$VALUE_2}%")

LIKE Condition in PHP Not Work correctly

i have a row in my database with name "active_sizes" and i want filter my website items by size, for this, i use LIKE Condition in php :
AND active_sizes LIKE '%" . $_GET['size'] . "%'
but by using this code i have problem
for example when $_GET['size']=7.0 this code shows items that active_sizes=17.0
my active_sizes value looks like 17.0,5.0,6.5,7.5,,
thanks
Using comma-separated values in a single field in a database is indicative of bad design. You should normalize things, and have a seperate "item_sizes" table. As it stands now, you need a VERY ugly where clause to handle such sub-string mismatches:
$s = (intval)$_GET['size'];
... WHERE (active_sizes = $s) // the only value in the field
OR (active_sizes LIKE '$s%,') // at the beginning of the field
OR (active_sizes LIKE '%,$s,%') // in the middle of the field
OR (active_sizes LIKE '%,$s') // at the end of the field
Or, if you normalized things properly and had these individual values in their own child table:
WHERE (active_sizes_child.size = $s)
I know which one I'd choose to go with...
You don't state which DB you're using, but if you're in MySQL, you can temporarily accomplish the same thing with
WHERE find_in_set($s, active_sizes)
at the cost of losing portability. Relevant docs here: http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_find-in-set
You Have % signs around your $_GET value. Combined with LIKE, this means that any string that simply contains your get value will be retuned. If you want an exact match, use the = operator instead, without the percentage signs.
This will solve your immediate issue:
AND active_sizes LIKE '" . mysql_real_escape_string($_GET['size']) . "%'
If you are using the database other than MySQL, use corresponding escape function. Never trust input data.
Besides, I'd suggest using numeric field (DECIMAL or NUMERIC) for active_sizes field. This will accelerate your queries, will let you consume less memory, create queries like active_sizes BETWEEN 16.5 AND 17.5, and generally this is more correct data type for a shoe size.

zend search lucene query api: boosting a term

I am using zend search lucene, and would like to add boosts to some of my search terms.
The code is already written using the query construction API as follows.
$query->addTerm(new Zend_Search_Lucene_Index_Term($name,'name'), null);
I tried writing
$query->addTerm(new Zend_Search_Lucene_Index_Term($name . "^10", 'name'), null);
But that appears not to work correctly. (I suddenly get no results at all).
This carat syntax is listed in the documentation for query language, but not in the docs for query construction API. I know that in some instances the API doesn't behave quite like plain query language. Is this one of those instances?
Is there a function or parameter that adds boost values to terms?
Try outputting your query by doing something like this:
$term = new Zend_Search_Lucene_Index_Term($name,'name');
$query = new Zend_Search_Lucene_Search_Query_Term($term);
echo $query;
This will allow you to see the query that is being created before you use it to execute a search.

Wildcard mysql LIKE or IN array values issue

I have the following code block which explodes a string upon spaces.
$run = explode(" ",strtolower($q));
eg. "This is the string"
Array $run look like:
(This,is,the,string)
The problems im having are:
I only want to explode the string if it has a white, something equal as using php function str_word_count($q)>1.
Unsure on how to create a single query which will work with multiple words in string and search table using any of them.
$query = "SELECT name FROM `table1` WHERE name LIKE '%". mysql_real_escape_string($run[0]) ."%' OR name LIKE '%". mysql_real_escape_string($run[1]) ."%'";
Trying to simplyfy the above query making it smaller and variable in size based on word count. Is this also a good aproach to exploding the string then preparing the sql?
I've tried using IN as well on SQL query with no good luck.
You can use MySQL's MATCH . . . AGAINST . . . to perform this kind of search:
WHERE MATCH (name) AGAINST ('this is the string')
Consult the documentation for more information.
Original solution, not helpful in this situation:
You can check out the MySQL specific function FIND_IN_SET:
WHERE FIND_IN_SET(colname, 'This,is,the,string') > 0
The value in colname cannot contain a comma, however.

MySQL: How to search for spelling variants? ("murrays", "murray's" etc)

I want to search like this: the user inputs e.g. "murrays", and the search result will show both records containing "murrays" and records containing "murray's". What should I do in my query.pl?
What do you think about using the SOUNDEX function and the SOUNDS LIKE operator ?
That way, you can simply do:
SELECT * from USERS WHERE name SOUNDS LIKE 'murrays'
I'm pretty sure it doesn't work for every case, and perhaps it is not the most efficient way to solve the problem, but it could fit your needs.
This won't help if you absolutely need to do these queries in SQL, but if you can set up a Lucene search index for it, you gain a lot of this kind of "fuzzy search" functionality. Note though that Lucene is quite a complex topic by itself.
What you could do is create an extra field in the database, which contains the data with all special characters stripped from it, and search there. A bit lame, I know. Looking forward to see smarter answers ;)
Quick and dirty:
SELECT * FROM myTable WHERE REPLACE(name, '\'', '') = 'murrays'
I would first build a search column which has the text without punctuation and then search on that. Otherwise you'll have have to have a series of regular expressions to search against or check individual records in PHP for matching: both of which are computational intensive operations.
Maybe something like this: (untested!)
SELECT * FROM users WHERE REPLACE(user_name, '\'', '') = "murrays"
If this is for single word searching, you could try using Soundex or Metaphone functions? These would handle sounds-like as well as spelling
Not sure if MySQL has these, but PHP does (which would require separate columns to hold these values).
Otherwise, Richy's no-punctuation extra column seems best.
You could try adding a replace to your query like this
replace(name, '''','')
to temporarily get rid of the apostrophes for the match.
select name from nametable where name = replace(name,'''','');
This query should be able to pick up "murrays" or "murray's".
var inputStr = "murrays";
inputStr = String.Replace("'", "\'", inputStr);
SELECT * FROM ATable WHERE Replace(AField, '\'', '') = inputStr OR AField = inputStr
strip user input and names in database from all non-letter characters.
Use levenstein distance or soundex to find murrays with murray or marrays. This is optional but your users would love that.

Categories