Execute category search Sphinx php - php

Good time of day!
There is such config Sphinx
source txtcontent : ru_config
{
sql_query = SELECT `id` as `txt_id`, 1 as index_id, `type_id`,`content_type_id`, `title`, `annonce`, `content` FROM `TxtContent` WHERE `status` = 1 AND `content_type_id` != 14
sql_attr_uint = index_id
sql_attr_uint = type_id
}
The entire table is indexed, and is stored in one large search index.
When it comes to find what is in it then all works OK
But today the task was to search for categories
The categories described in the field and have a type_id of type int
How in php using SphinxAPI to perform such a search?
Standard search looks like this.
$sphinxClient = new SphinxClient();
$sphinxClient->SetServer("127.0.0.1", 3312 );
$sphinxClient->SetLimits( 0, 700,700 );
$sphinxClient->SetSortMode(SPH_SORT_RELEVANCE);
$sphinxClient->SetArrayResult( true );
$result = $sphinxClient->Query( $this->query, 'txtcontent provider item');
I tried to add
$sphinxClient->SetFilter('type_id','1');
To search only where type_id = 1 but it didn't help.
Actually how can I search for a specific category? option to find everything in php to let go of the result excess is not considered (otherwise, the search will then be saturada existing limit) how to do it "properly" via the API without placing each topic in a separate search index?

setFilter takes an Array of values. And they need to be numeric (type_id is a numeric attribute)
$sphinxClient->SetFilter('type_id',array(1));
The sphinxapi class actully uses assertions to detect invalid data like this, which I guess you have disabled (otherwise would of seen them!).

Related

How to display specific data in jasper Report?

I am beginner in Jasper report, i have created a jasper report table which contains more than one million data. I want to display the jasper report as per the user need.I have database in PostgreSQL named "Banke" and table named Arsenic_Test.i want to make a choice for my user to select the data, For example I have 3 options for the user to select "data with value X<50, X=50 or X>50. How to do this?
You need to use parameters in your queries.
For example your query can look like
SELECT * FROM some_table WHERE X < $P{value_lower}
Ofcourse you have to prepare more complicated query. I think you need a 3 parameters - one for <, another for = and the last for > and check them if they are not nulls in where cluase (because you can't provide an operation with parameter but just only the value). For example you can use something like this
SELECT *
FROM some_table
WHERE ($P{value_lower} is not null and X < $P{value_lower})
OR ($P{value_equal} is not null and X = $P{value_equal})
OR ($P{value_higher} is not null and X > $P{value_higher})
If you need more information about using parameters then look at for example this tutorial or if you want to learn more about connect JR with your site then you should look at http://community.jaspersoft.com/wiki/php-client-sample-code (specially at Reporting Services section). For example if you want know how to provide inputs then you should look at this example
$controls = array(
'Country_multi_select' => array('USA', 'Mexico'),
'Cascading_state_multi_select' => array('CA', 'OR')
);
$report = $c->reportService()->runReport('/reports/samples/Cascading_multi_select_report', 'html', null, null, $controls);
echo $report;

MySQL select only using first word of variable

I am using php and mySQL. I have a select query that is not working. My code is:
$bookquery = "SELECT * FROM my_books WHERE book_title = '$book' OR book_title_short = '$book' OR book_title_long = '$book' OR book_id = '$book'";
The code searches several title types and returns the desired reference most of the time, except when the name of the book starts with a numeral. Though rare, some of my book titles are in the form "2 Book". In such cases, the query only looks at the "2", assumes it is a "book_id" and returns the second entry in the database, instead of the entry for "2 Book". Something like "3 Book" returns the third entry and so forth. I am confused why the select is acting this way, but more importantly, I do not know how to fix it.
If you have a column in your table with a numeric data type (INT, maybe), then your search strategy is going to work strangely for values of $book that start with numbers. You have discovered this.
The following expression always returns true in SQL. It's not intuitive, but it's true.
99 = '99 Luftballon'
That's because, when you compare an integer to a string, MySQL implicitly does this:
CAST(stringvalue AS INT)
And, a cast of a string beginning with the text of an integer always returns the value of the integer. For example, the value of
CAST('99 Luftballon' AS INT)
is 99. So you'll get book id 99 if you look for that search term.
It's pointless to try to compare an INT column to a text string that doesn't start with an integer, because CAST('blah blah blah' AS INT) always returns zero. To make your search strategy work better, you should consider omitting OR book_id = '$book' from your search query unless you know that the entirety of $book is a number.
As others mention, my PHP allowed both numerical enties and text entries from the browser. My query was then having a hard time with this, interpreting some of my text entries as numbers by truncating the end. Thus, my "2 Book" was being interpreted as the number "2" and then being queried to find the second book in the database. To fix this I just created a simple if statement in PHP so that my queries only looked for text or numbers. Thus, in my case, my solution was:
if(is_numeric($book)){
$bookquery = "SELECT * FROM books WHERE book_id = '$book'";
}else{
$bookquery = "SELECT * FROM books WHERE book_title = '$book' OR book_title_short = '$book' OR book_title_long = '$book'";
}
This is working great and I am on my way coding happily again. Thanks #OllieJones and others for your questions and ideas which helped me see I needed to approach the problem differently.
Not sure if this is the correct answer for you but it seems like you are searching for only exact values in your select. Have you thought of trying a more generic search for your criteria? Such as...
$bookquery = "SELECT * FROM my_books WHERE book_title LIKE '".$book."' OR book_title_short LIKE '".$book."' OR book_title_long LIKE '".$book."' OR book_id LIKE '".$book."'"
If you are doing some kind of searching you might even want to ensure the characters before the search key are found as well like so....
$bookquery = "SELECT * FROM my_books WHERE book_title LIKE '%".$book."' OR book_title_short LIKE '%".$book."' OR book_title_long LIKE '%".$book."' OR book_id LIKE '%".$book."'"
The % is a special char that looks for allows you to search for the chars you want to search for PLUS any characters before this that aren't in the search criteri... for example $book = "any" with a % before hand in the query like so, '%".$book."'"`` would return bothcompanyand also the wordany` by itself.
If you need to you can add a % to the end also like so, `'%".$book."%'"`` and it would do the same for the beginning and end of the search key

Sphinx problem. Filter

I have a problem with Sphinx. I have configuration like this:
sql_query = \
SELECT id, product_title, product_inf, product_code, ptype_name, title, cat, value, car \
FROM Catalog_View;
sql_attr_uint = car
sql_attr_uint = cat
Catalog_View is a view which collect data from several tables. It works good and haven't got any problem. I created index with this configuration:
index src1
{
source = src1
path = /var/data/src1
docinfo = extern
mlock = 0
morphology = stem_en, stem_ru
min_word_len = 3
charset_type = sbcs
min_prefix_len = 0
min_infix_len = 3
enable_star = 1
}
And indexer done his job perfect. But when I'm looking for empty query (like this '') and setup two filters
$cl->SetFilter('cat',array(9));
$cl->SetFilter('car',array(2));
I loose a lot of matches. For example when I use SQL-query to Catalog_View I have 76 rows, and the same in Sphinx gives me only 11 rows. I can't figure out what am i doing wrong. Everything seems fine except filter.
Actually I have the same problem with filters when I'm looking for non-empty query.
I stumbled upon this one too. My solution was making document IDs unique. If you have duplicated document IDs the possible result can be the same. I suppose Sphinx would take only first unique document thrashing all duplicated data.

create mention like twitter or convore with php

hello im just curious. about how they do stuff. what i assume they do something like this
#someone1 im stacking on stackoverflow RT #someone2 : hello guys what are you doing?
before i do it in my way i want to tell you about my database scheme
// CID = COMMENT ID, BID = BLOG ID, UID = USER ID
CID BID UID COMMENT
1 1 1 #someone1 im stacking on stackoverflow RT #someone2 : ....
2 1 4 #someone1 im stacking on stackoverflow RT #someone2 : ....
3 1 12 #someone1 im stacking on stackoverflow RT #someone2 : ....
they use regex to do like this to take the #someones name
preg_match_all("/#[a-zA-Z0-9_]+/", $text, $matches);
then they get the # off each name
foreach ($matches as $value) {
foreach ($value as $value) {
$usernames[] = substr($value, 1);
}
}
then they get the UID from the database from doing something like this
foreach ($username as $value) {
# insert database one by one ? so it will be like the example above
}
then we can just output the comment buy geting the UID.
then somhow we can get all the comments in the blog. ( without a same comment ) where blog buid = 1 and give them an notification on every user by where uid = :uid.
is there any better way doing this ? something like twitter or convore ?
Thanks for looking in
Adam Ramadhan
I have done something similar to this with an in-house application that we use for communication.
Basically, you are going to have two tables: status_updates and mentions. Each status update has many mentions. Whenever someone creates a status update, you save it to the status_updates table. During this process, you can also use Regex to detect any #username "mentions". When you find a mention, you add it to your mentions table. For example, your mentions table might look something like this:
mention_id (Auto-incrementing key) | status_message_id | username_id
That way if you want to see if someone is mentioned in a status message you can do a quick lookup in the status_messages table, as opposed to loading up the status message and running the Regex each time. The other nice thing about this approach is that it allows you to have multiple mentions in each status message. Just create a record in mentions for each.
That's the basic way that we have set it up.
EDIT: If you wanted to pull an "activity feed" for a given user, showing only the status updates in which they have been mentioned, it would be as simple as:
SELECT * FROM mentions m LEFT JOIN status_messages s ON m.status_message_id = s.id WHERE m.username_id = $username_id
I should note that this is not how they do it at Twitter, because they are dealing with issues of scale that would make this simple way of doing things impossible. However, I think this is the simplest solution that works well if you aren't worried about scaling to hundreds of thousands of users. If you are, then you probably have more issues on your hands than this.
You can use it like bb codes but instead of taken it like [foo] [/foo] you take the # and end it at the space ... before it's insert into your database you take another script and break the # after the space. and put the mention into a separate column then use bbcodes to make the mention on the fly
Example..
if ( strstr("$status", "#") ) {
$explodeat = explode("#", $status);
$explodeat1 = explode(" ", $explodeat[1]);
$status=$explodeat1[0];
}
and insert $status into your mentions column in your database... The BB code for it after that won't be so hard
I think in MySQL, you can use DISTINCT to avoid duplicates rows:
Something link this:
SELECT `CID`, `BID`, DISTINCT `COMMENT`
FROM comments
WHERE UID = :uid
AND ##Others clauses for bloc here##

MySQL/PHP Search Efficiency

I'm trying to create a small search for my site. I've tried using full-text index search, but I could never get it to work. Here is what I've come up with:
if(isset($_GET['search'])) {
$search = str_replace('-', ' ', $_GET['search']);
$result = array();
$titles = mysql_query("SELECT title FROM Entries WHERE title LIKE '%$search%'");
while($row = mysql_fetch_assoc($titles)) {
$result[] = $row['title'];
}
$tags = mysql_query("SELECT title FROM Entries WHERE tags LIKE '%$search%'");
while($row = mysql_fetch_assoc($tags)) {
$result[] = $row['title'];
}
$text = mysql_query("SELECT title FROM Entries WHERE entry LIKE '%$search%'");
while($row = mysql_fetch_assoc($text)) {
$result[] = $row['title'];
}
$result = array_unique($result);
}
So basically, it searches through all the titles, body-text, and tags of all the entries in the DB. This works decently well, but I'm just wondering how efficient would it be? This would only be for a small blog, too. Either way I'm just wondering if this could be made any more efficient.
There's no way to make LIKE '%pattern%' queries efficient. Once you get a nontrivial amount of data, using those wildcard queries performs hundreds or thousands of times slower than using a fulltext indexing solution.
You should look at the presentation I did for MySQL University:
http://www.slideshare.net/billkarwin/practical-full-text-search-with-my-sql
Here's how to get it to work:
First make sure your table uses the MyISAM storage engine. MySQL FULLTEXT indexes support only MyISAM tables. (edit 11/1/2012: MySQL 5.6 is introducing a FULLTEXT index type for InnoDB tables.)
ALTER TABLE Entries ENGINE=MyISAM;
Create a fulltext index.
CREATE FULLTEXT INDEX searchindex ON Entries(title, tags, entry);
Search it!
$search = mysql_real_escape_string($search);
$titles = mysql_query("SELECT title FROM Entries
WHERE MATCH(title, tags, entry) AGAINST('$search')");
while($row = mysql_fetch_assoc($titles)) {
$result[] = $row['title'];
}
Note that the columns you name in the MATCH clause must be the same columns in the same order as those you declared in the fulltext index definition. Otherwise it won't work.
I've tried using full-text index search, but I could never get it to work... I'm just wondering if this could be made any more efficient.
This is exactly like saying, "I couldn't figure out how to use this chainsaw, so I decided to cut down this redwood tree with a pocketknife. How can I make that work as well as the chainsaw?"
Regarding your comment about searching for words that match more than 50% of the rows.
The MySQL manual says this:
Users who need to bypass the 50% limitation can use the boolean search mode; see Section 11.8.2, “Boolean Full-Text Searches”.
And this:
The 50% threshold for natural language
searches is determined by the
particular weighting scheme chosen. To
disable it, look for the following
line in storage/myisam/ftdefs.h:
#define GWS_IN_USE GWS_PROB
Change that line to this:
#define GWS_IN_USE GWS_FREQ
Then recompile MySQL. There is no need
to rebuild the indexes in this case.
Also, you might be searching for stopwords. These are words that are ignored by the fulltext search because they're too common. Words like "the" and so on. See http://dev.mysql.com/doc/refman/5.1/en/fulltext-stopwords.html
Using LIKE is NOT fulltext.
You need to use ... WHERE MATCH(column) AGAINST('the query') in order to access a fulltext search.
MySQL Full-text search works -- I would look into it and debug it rather than trying to do this. Doing 3 separate MySQL queries will not be anywhere near as efficient.
If you want to try to make that much efficient you could separate the LIKE statements in one query with OR between them.

Categories