Searching through multiple fields in SphinxSearch (PHP) - php

I have the following code:
$this->api = new App_Other_SphinxSearch();
$this->api->SetServer($host, $port);
$this->api->SetConnectTimeout(1);
$this->api->SetArrayResult(true);
$results = $this->api->Query("#(title,content) test", 'members');
echo "<pre>";print_r($results);die;
According to their documentation, a syntax like #(field_1,field_2) query should return docs which match the string query in either field_1 or field_2.
The PHP SDK returns something entirely different:
Array
(
[error] =>
[warning] =>
[status] => 0
[fields] => Array
(
[0] => title
[1] => content
)
[attrs] => Array
(
[created] => 2
[content] => 7
)
[total] => 0
[total_found] => 0
[time] => 0.000
[words] => Array
(
[title] => Array
(
[docs] => 10
[hits] => 34
)
[content] => Array
(
[docs] => 34
[hits] => 139
)
[test] => Array
(
[docs] => 26
[hits] => 34
)
)
)
There is no matches key in the array, however it got some hits. I don't really understand why this is happening, especially because if I try the same query from the command line, everything works correctly.
Any help?
Edit: Querying like this works though: #* test. Not really what I want though, cause that searches in all fields.

[total_found] => 0 says there where no matches.
The words array, just tells you now many documents and how many times that word appears in ANY (and all) fields. (WITHOUT regard to your specific query)
Sphinx caches those word stats, which help it make quick sanity checks on queries. When the query runs it can end up not matching any documents (because only then does it apply the field level filters), even though the individual words are found.
That explains your misinpretation of the results, but not why getting the results you get.
You are entering a Extended Mode query (as evidenced by the link to the sphinx documentation) , but the sphinx API defaults to ALL query mode. Notice also that title and content are in the words array, so are being taken as plain keywords not as syntax.
So you need to include a
$this->api->SetMatchMode(SPH_MATCH_EXTENDED);
btw, #* test, works because the #* are simply ignored in ALL query mode.

Related

Opencart event data missing identifier

Using opencart 3 and trying to make use of the events but I'm unable to find the identifier.
E.g trying to extend the returns form added an event:
$this->model_setting_event->addEvent('mail_account_return_after', 'catalog/model/account/return/addReturn/after', 'extension/module/return/returnAdd');
Controller:
class ControllerExtensionModuleReturn extends Controller {
public function returnAdd(&$route, &$args, &$output) {
print_r($args);
exit;
$args is missing the main return_id identifier:
Array
(
[0] => Array
(
[firstname] => Foo
[lastname] => Bar
[email] => test#gmail.com
[telephone] => 01234556789
[order_id] => 29
[date_ordered] => 2017-06-29
[product] => Canon EOS 5D
[model] => Product 3
[quantity] => 1
[return_reason_id] => 4
[opened] => 0
[comment] => Test comment
)
)
Tried with $this->db->getLastId() but this returns 0. Tested with other events and appears to be missing the main identifiers.
Where does opencart set what data is passed to the before/after events?
If I'm not mistaken you should be able to access the auto increment return_id in $output, which holds the output of method addReturn(), i.e., $this->db->getLastId();.
As to why calling getLastId() a second time from within your event doesn't work, that's a good question. I would assume there may be some other query happening in between - though by default I don't think there should be. Is it possible there is another trigger running a query before your event gets triggered?
Look in system/engine/loader.php at for the strings before and after. There are methods that do view, controller, configuration and language.

usort of session array not outputting as expected

I have a grid of img squares that can be dragged into any order using the sortable library. Each img is a visual representation of a result from a mySQL db query that selects any image that shares an 'imageparent' identifier. The order they're presented in the grid is taken from the 'imageorder' column in the database and starts at 0 and works in sequence up to the nth number of images returned.
The purpose of dragging the img grid is to be able to change the 'imageorder' index. On completion of the drag, the sortable library POSTS an 'imageorder' var by ajax to service.php and is received correctly. So rather than the original 0,1,2,3,4,5,6,7 order of the original, it sends a string like 2,1,0,3,4,5,7,6. Not too hard to grasp. After I switch the order the orderList var sent to service.php is always correct, but the array I end up sending to the db and setting as my session var becomes a little garbled in order after the second or third drag and I'm not quite sure why.
Code Examples and Comments
$_SESSION['selectedCsImages'] Array structure:
[0] => Array
(
[imagename] => "Title"
[imageorder] => 0
[imageid] => 43
)
[1] => Array
(
[imagename] => "Title"
[imageorder] => 1
[imageid] => 21
)
[2] => Array
(
[imagename] => "Title"
[imageorder] => 2
[imageid] => 3
)
etc...
Services.php extract:
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
// Turn the orderList posted into an array
$removeChars = array('"','[',']');
$orderList = str_replace($removeChars, "", $_POST['order']); // POST received fine.
$listArray = explode(",",$orderList);
// Retrieve the session array
$sorting = $_SESSION['selectedCsImages'];
/* My logic is that I compare the $sorting array to $listArray and reorder $sorting by 'imageorder' to match $listarray */
usort($sorting, function($a, $b) use ($listArray) {
return array_search($a['imageorder'], $listArray) - array_search($b['imageorder'], $listArray);
});
/* I now have a $sorting array that (sometimes, hence the problem) matches the order that the images had just been dragged into by the user. Typically, as I mentioned above, it's correct after the first drag, but not always after the second or third where it creates a new order that I can't see a pattern or logic in. */
/* Had there not been errors with the usort function, I (would) have a $sorting array in the order I want but with imageorder values referring to pre-sorting. I iterate through the array and set each key to 0, 1, 2, etc. so that I have an array in the correct order and with each imageorder correctly stating its place.*/
$i = 0;
foreach ($sorting as $key => $value) {
$sorting[$key]['imageorder'] = $i;
$i++;
}
/* The information is attempted to be sent to the db and, on success I update the session var */
// Database code (runs succesfully and updates the db as per the image orders found in the $sorting array)
$_SESSION['selectedCsImages'] = $sorting;
Debugging:
From debugging, it appears that something happens with the usort function when I call this page from ajax for the second or third time. Everything after this follows through fine and processes the correct or incorrect order as per expectations. The orderList var posted by sortable is correct each time. I'd provide a sample of the $sorted var after usort each time but it's as simple to describe it as the above array example in an order I didn't specify after dragging and I can't see a pattern in the seemingly random order it outputs.
From researching, I had thought that it was an issue with session vars being retained until the page is refreshed but it appears that the ajax call to services.php should refresh the $_SESSION['selectedCsImages'] var. I had also read that, perhaps, I was unknowingly using referenced array values and - as I source from a session var to a new array and, ultimately, save back to this session var from this array - I may have created some messy referencing feedback. However, I tried using $sorted = (array)clone(object)$_SESSION['selectedCsImages']; before attempting usort and the results didn't change.
PHP error logs are showing nothing.
Updates:
Per the suggestion of #Ayaou, I've checked the output of $listArray and am getting some unexpected results. I'd wrongly assumed that as the posted $orderList was correct, that the exploded array would not be a culprit.
Here's the output of print_r($listArray) after completing the following order swaps of 16 img elements: 1st with 2nd, 2nd last with last,6th with 7th:
1st and 2nd:
(
[0] => 1
[1] => 0
[2] => 2
[3] => 3
[4] => 4
[5] => 5
[6] => 6
[7] => 7
[8] => 8
[9] => 9
[10] => 10
[11] => 11
[12] => 12
[13] => 13
[14] => 14
[15] => 15
)
last and 2nd last:
(
[0] => 1
[1] => 0
[2] => 2
[3] => 3
[4] => 4
[5] => 5
[6] => 6
[7] => 7
[8] => 8
[9] => 9
[10] => 10
[11] => 11
[12] => 12
[13] => 13
[14] => 15
[15] => 14
)
6th with 7th:
(
[0] => 1
[1] => 0
[2] => 2
[3] => 3
[4] => 4
[5] => 6
[6] => 5
[7] => 7
[8] => 8
[9] => 9
[10] => 10
[11] => 11
[12] => 12
[13] => 13
[14] => 15
[15] => 14
)
I was progressing with the idea that $listArray would show a sequential 0,1,2,3,etc. each time with only the two swapped items showing order changes. As it's not, I'll look back again at $orderList and check if my sortable library is updating the orders it's obtaining correctly from the updated session var. Older order swaps are being retained somewhere along the chain where they shouldn't.
The solution is on your sortable form (on the front end), so instead of sending the imageorder on your 'order' post data, send the imageid index.
Then change your sort callback like this
//Use imageid index instead of imageorder
usort($sorting, function($a, $b) use ($listArray) {
return array_search($a['imageid'], $listArray) - array_search($b['imageid'], $listArray);
});

How can one split an array to insert it into another for an SQL query?

I have the array $total as depicted with pint_r:
Array
(
[0] => 1,2,3,4,5,6,7,8,9,10,11,12,1
[1] => 13,14,15,16,17,18,19,20,21,22,23,24,1
[2] => 25,26,27,28,29,30,31,32,33,34,35,36,1
[3] => 37,38,39,40,41,42,43,44,45,46,47,48,1
[4] => 49,50,51,52,53,54,55,56,57,58,59,60,1
[5] => 61,62,63,64,65,66,67,68,69,70,71,72,1
[6] => 73,74,75,76,77,78,79,80,81,82,83,84,1
[7] => 85,86,87,88,89,90,91,92,93,94,95,96,1
[8] => 97,98,99,100,101,102,103,104,105,106,107,108,1
[9] => 109,110,111,112,113,114,115,116,117,118,119,120,1
[10] => 121,122,123,124,125,126,127,128,129,130,131,132,1
[11] => 133,134,135,136,137,138,139,140,141,142,143,144,1
[12] => 145,146,147,148,149,150,151,152,153,154,155,156,1
[13] => 157,158,159,160,161,162,163,164,165,166,167,168,1
[14] => 169,170,171,172,173,174,175,176,177,178,179,180,1
[15] => 181,182,183,184,185,186,187,188,189,190,191,192,1
[16] => 193,194,195,196,197,198,199,200,201,202,203,204,1
[17] => 205,206,207,208,209,210,211,212,213,214,215,216,1
[18] => 217,218,219,220,221,222,223,224,225,226,227,228,1
[19] => 229,230,231,232,233,234,235,236,237,238,239,240,1
[20] => 241,242,243,244,245,246,247,248,249,250,251,252,1
[21] => 253,254,255,256,257,258,259,260,261,262,263,264,1
[22] => 265,266,267,268,269,270,271,272,273,274,275,276,1
[23] => 277,278,279,280,281,282,283,284,285,286,287,288,1
)
What my goal is, is to make an SQL insert query that inputs each of these numbers into a MYSQL table, each number 2 a row. Ending in a table with 288 rows labeled 1-288 in the column PortNUmbers
(please ignore the trailing 1, it seems to have taged along for the ride when i ran sort()) so this is my SQL:
$sqlinsert='
INSERT INTO '.$tbl_name.'
(PortNumber) VALUES (1),(2),(3)etc..';
pretty simple, i would just explode it put it in a while loop and then implode for the query, however I need the values to be inserted in in a rather odd order, like so:
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(145),(146),(147),(148),(149),(150),(151),(152),(153),(154),(155),(156)
and so on following that same pattern until the end is met. Any one have any ideas as to how i could achieve this?
SQL tables have no implicit order. You shouldn't rely on the order you insert values being the order in which they will be returned when you query them. You must use ORDER BY to have a dependable order for a query result.
If you need to record the order in which you input the data, you need another column.
For example:
CREATE TABLE TblName (
id INT AUTO_INCREMENT PRIMARY KEY,
PortNUmber INT NOT NULL
);
INSERT INTO TblName (PortNumber) VALUES
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12);
...etc...
The auto-increment will preserve the order in which you inserted the values, and then you can insert the values in a rather odd order instead of numerical order however you wish.

PHP Zend Lucene Search Query with multiple criteria fail

Zend Lucene Search Document
Lucene Document
pk:Keyword
category_id:Keyword
title:UnStored
description:UnStored
This is my string query "java lucene AND +category_id:7".
Result here:
Array
(
[0] => Array
(
[pk] => 209
[category_id] => 7
[id] => 0
[score] => 0.40750848701418
)
[1] => Array
(
[pk] => 225
[category_id] => 7
[id] => 3
[score] => 0.30750848701619
)
[2] => Array
(
[pk] => 211
[category_id] => 8 ====>>> WRONG!!!
[id] => 2
[score] => 0.37152213415004
)
)
Can you do a Query search on the category_id = 7 only??
Thanks in advance.
I had solved this problem by using Zend Query Parsing
$strQuery = Zend_Search_Lucene_Search_QueryParser::parse('java lucene');
$cateTerm = new Zend_Search_Lucene_Index_Term(7 , 'category_id');
$cateQuery = new Zend_Search_Lucene_Search_Query_Term($cateTerm);
$query = new Zend_Search_Lucene_Search_Query_Boolean();
$query->addSubquery($strQuery, true /* required */);
$query->addSubquery($cateQuery, true /* required */);
Results will be only in category_id = 7 :)
You can remove the AND +category_id:7 from you query, what you want is a filter since +category_id:7 is not needed as a ranked value.
I don't know how to implement it with Zend_Lucene but in solr I used to pass fq parameter, this may give you a hint :)
Filtering is a process that constrains the search space and allows only a subset of documents to be considered for search hits. You can use this feature to implement search-within-search results. Lucene comes with various built-in filters such as BooleanFilter, CachingWrapperFilter, ChainedFilter, DuplicateFilter, PrefixFilter, QueryWrapperFilter, RangeFilter, RemoteCachingWrapperFilter, SpanFilter, etc.(THE NATIVE JAVA VERSION) Filter can be passed to IndexSearcher's search method to filter documents that match the filter criteria.

saving cakephp date fields

I have a form that includes an hour and minute drop down using this: 'dateFormat'=>'NONE', 'timeFormat'=>'24' But now when i save the form $this->data ends up looking like the array below and because eventStartDate & eventStartDate are arrays it makes an SQL error saying eventStartDate can not be null etc.
Array
(
[Work] => Array
(
[eventStartDate] => Array
(
[hour] => 12
[min] => 00
)
[eventEndDate] => Array
(
[hour] => 12
[min] => 45
)
[description] => 234
[projectID] => 7105
[taskID] => 1
[userid] => 8
)
)
Shouldnt cakephp make these arrays into strings so they can be put into the database automatically?
What values for day, month etc will be used?
This might help, as it worked for me:
Your view code should look something like this
echo $form->dateTime('your_column_name', 'NONE', '24');

Categories