MultiQueries in Sphinx in cakephp - cakephp

$query = '#(name,email,bio) ' . '"' . $this->passedArgs['name'] . '"~100';
$query2 = '#(name,email,bio) ' . '"' . $this->passedArgs['name'] . '"~300'
$query3 = '#(name,email,bio) ' . '"' . $this->passedArgs['name'] . '"/3';
$query4 = '#(name,email,biot) ' . '"' . $this->passedArgs['name'] . '"/1';
I want to execute this in one query! If I use the "|" OR operator, it takes approx 2minutes to display the results!
Is there anyway using multiquery in sphinxapi I can combine all these queries into one?

You could try
#(name,email,bio) ( "one two"~100 | "one two"~300 | "one two"/3 | "one two"/1 )
Might be a bit quicker.

If I understand (from your comment), you're looking for $this->passedArgs['name'] in the #(name,email,bio) fields, within ~100 characters OR ~300 characters OR having at least /3 words matching OR at least /1 word matching?
Why not then split it out to two different queries, the most limiting first:
$query = '#(name,email,bio) ' . '"' . $this->passedArgs['name'] . '"~100';
$query4 = '#(name,email,bio) ' . '"' . $this->passedArgs['name'] . '"/1';
perform those queries, |d together. If you get no results from it, perform the below query, also |d together.
$query2 = '#(name,email,bio) ' . '"' . $this->passedArgs['name'] . '"~300'
$query3 = '#(name,email,bio) ' . '"' . $this->passedArgs['name'] . '"/3';

I tried the single query using OR(|) operator, Sphinx wasn't returning accurate results. Later found out AddQuery function which helped me in getting results from multiple queries and merging into one.
I can even specify separate indexes for each query. Refer Sphinx Documentation AddQuery
$cl->AddQuery('#(name,email,bio) "one two" ~100', 'dist');
$cl->AddQuery('#(name,email,bio) "one two" ~300', 'dist');
$cl->AddQuery('#(name,email,bio) "one two" ~300', 'dist');
$cl->AddQuery('#(name,email,bio) "one two" /3', 'dist');
$cl->AddQuery('#(name,email,bio) "one two" ~/1', 'metaphone dist');
$result = $cl->RunQueries();
echo "<pre>",print_r($result),"</pre>";
I did SetIndexWeights call to prioritize multiple indexes that I have used. Refer Sphinx Document SetIndexWeights

Related

Run a sql query from PS, and loop in criteria in the where clause

I have code where I'm creating an index file by parsing out pieces of a file name.
This file name:
25643245_AjaWar_Prav_2_FT_20200701.pdf
Will create this line in the index file:
256432245|ST|W-HIGH SCHOOL TRANSCRIPT|##TEST-LOCATION\25643245_AjaWar_Prav_2_FT_20200701.pdf
The problem is that the first parse of '256432245' isn't a primary key in our database, so I have to convert to a primary key, then store the primary key into the index file in place of '256432245'
I have part of the query that builds the index file working correctly, but not the part that queries and returns the converted ID. If I run only the part of the query that returns just one ID, that also works. I'm having a problem getting the query to work within the "foreach".
I currently get this a result:
|ST|W-HIGH SCHOOL TRANSCRIPT|##TEST-LOCATION\25643245_AjaWar_Prav_2_FT_20200701.pdf
When I want to get:
8992004|ST|W-HIGH SCHOOL TRANSCRIPT|##TEST-LOCATION\25643245_AjaWar_Prav_2_FT_20200701.pdf
Where '8992004' is the SPRIDEN_ID is the result of the sql query.
Thanks for any help you can provide.
foreach ($Filename in Get-ChildItem $ImagePath)
{
$Arr = $Filename -split '_'
$reworkedfilename = $Arr[0] + '_' + $Arr[1] + '_' + $Arr[2] + '_' + $Arr[3] + '_' + $Arr[4] + '_' + $Arr[5]
##$reworkedarray2 = $Arr[0] -replace ".pdf", "";
Write-host $Arr[0] ##this works because I can see the non-primary ID being returned
#Find Each SPRIDEN_ID translated from CAID
add-type -AssemblyName System.Data.OracleClient
$username = "U"
$password = "P"
$data_source = "DS"
$connection_string = "User Id=$username;Password=$password;Data Source=$data_source"
$statement = "
Select Distinct SPRIDEN_ID
from SARACMT, SPRIDEN
where
SPRIDEN_PIDM = SARACMT_PIDM
and SPRIDEN_CHANGE_IND is null
AND SARACMT_COMMENT_TEXT = '$Arr[0]'
"
##The "AND SARACMT_COMMENT_TEXT = '$Arr[0]'" doesn't work because nothing is being returned in the index file
try{
$con = New-Object System.Data.OracleClient.OracleConnection($connection_string)
$con.Open()
$cmd = $con.CreateCommand()
$cmd.CommandText = $statement
$result = $cmd.ExecuteReader()
# Do something with the results...
$ArrConverted = while ($result.Read()) {
$result.GetString(0)
}
} catch {
Write-Error (“Database Exception: {0}`n{1}” -f `
$con.ConnectionString, $_.Exception.ToString())
} finally{
if ($con.State -eq ‘Open’) { $con.close() }
}
$outputline = $ArrConverted + '|' + $Arr[4] + '|' + $DocType + '|##'+ $ImagePath + $reworkedfilename | out-file -filepath $IndexFilePath -Encoding "ascii" -append
#>
}
Your issue is to do with how you’re trying to inject variable values into your sql query string:
$statement = "
Select Distinct SPRIDEN_ID
from SARACMT, SPRIDEN
where
SPRIDEN_PIDM = SARACMT_PIDM
and SPRIDEN_CHANGE_IND is null
AND SARACMT_COMMENT_TEXT = '$Arr[0]'
"
If you add a write-host $statement after this line you’ll see it’s replacing just the $Arr part and not the $Arr[0] part, so your query contains something like:
Select Distinct SPRIDEN_ID
from SARACMT, SPRIDEN
where
SPRIDEN_PIDM = SARACMT_PIDM
and SPRIDEN_CHANGE_IND is null
AND SARACMT_COMMENT_TEXT = '25643245 AjaWar Prav 2 FT 20200701[0]'
instead of:
Select Distinct SPRIDEN_ID
from SARACMT, SPRIDEN
where
SPRIDEN_PIDM = SARACMT_PIDM
and SPRIDEN_CHANGE_IND is null
AND SARACMT_COMMENT_TEXT = '25643245’
To get it to replace the value of $Arr[0] you can surround it with $( ... ) to use “command substitution” (see https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-string-substitutions?view=powershell-7#command-substitution) so your query becomes:
$statement = "
Select Distinct SPRIDEN_ID
from SARACMT, SPRIDEN
where
SPRIDEN_PIDM = SARACMT_PIDM
and SPRIDEN_CHANGE_IND is null
AND SARACMT_COMMENT_TEXT = '$($Arr[0])’
Having said that, you’d be much better off using a parameterised query rather than building a dynamic sql string (see Oracle Parameterized query in c#) because as your code stands it’s vulnerable to a sql injection attack if you come across a deliberately mischievous file name (e.g. ‘ or 1='1_AjaWar_Prav_2_FT_20200701.pdf).
See https://blogs.oracle.com/sql/what-is-sql-injection-and-how-to-stop-it for more about sql injection attacks.
Just by sheer luck I figured it out.
I created a variable for $Arr[0]
$Arr0 = $Arr[0]
Then put the new variable in the where clause of where clause of the sql statement:
AND SARACMT_COMMENT_TEXT = '$Arr0'
This ran the query on each item parsed out during the foreach.

error while converting json array to csv using perl

im using a perl script to convert from JSON to csv. the sampple json is like this,
[{"id":100,
"primary-codes":["E0181V00","E0226V00"],
"substitute-codes":["E0181D00","E0226100"],
"fk-id":2294}]
and the perl code i used to convert this to csv is,
#!/usr/bin/perl
use utf8;
use warnings;
use strict;
use lib '.';
use JSON::PP qw(decode_json);
my $json;
{
local $/;
open my $fh, '<', 'output_array.json' or die $!;
$json = <$fh>;
}
my $perl = decode_json $json;
my $filename = 'sample.csv';
open(my $fh, '>>:encoding(UTF-8)', $filename) or die "Could not open file '$filename' $!";
say $fh 'nk_id,prim_cd,sub_cd,fk_id';
for (#$perl){
my $nk_id = '"' . $_->{"id"} . '"';
my $prim_cd= '"' . $_->{"primary-codes"} . '"';
my $sub_cd= '"' . $_->{"substitute-codes"} . '"';
my $fk_id= '"' . $_->{"fk-id"} . '"';
say $fh "$nk_id," . "$prim_cd," . "$sub_cd," . "$fk_id";
}
close $fh;
The output i get is like this,
nk_id,prim_cd,sub_cd,fk_id
100,ARRAY(0x201549f8),ARRAY(0x20154a88),2294
but i want it to be,
100,"E0181V00,E0226V00","E0181D00,E0226100",2294
i tried using ,
my $prim_cd = '"' . join ",", #{ $perl->[0]{"primary-codes"} } . '"';
But it just returns the count and not the elements.
Please help me out with this issue.
Thanks!
The one detail that subverted your honest attempt is the precedence. In
my $prim_cd = '"' . join ",", #{ $perl->[0]{"primary-codes"} } . '"';
the list #{ $perl->[0]...} is first concatenated (.) with ", and as the . operator imposes scalar context the number of elements in the list is used, yielding 2". Only then does join do its thing, "joining" the given list (which is a single element, 2")
Just add parenthesis
for (#$perl){
my $nk_id = '"' . $_->{"id"} . '"';
my $prim_cd = '"' . join(',', #{$_->{'primary-codes'}}) . '"';
my $sub_cd = '"' . join(',', #{$_->{'substitute-codes'}}) . '"';
my $fk_id = '"' . $_->{"fk-id"} . '"';
say $fh "$nk_id,$prim_cd,$sub_cd,$fk_id";
}
A few notes.
You forgot use feature qw(say); without which say won't work.
What is shown has no use of use utf8;, which is about the source file itself
What is shown doesn't need use lib; that specifies paths to be searched for modules. (It won't help in finding files, if that was the idea.). However, once we are at it ...
I avoid using . as it can create problems ranging from confusion to direct errors. For one, do you mean the current working directory, or the directory of the script? They aren't the same. Assuming that you use it for the script's directory (which it isn't), replace it with
use FindBin qw($RealBin);
use lib $RealBin;
To slurp a file you can also do
my $json = do {
local $/;
open my $fh, '<', 'output_array.json' or die $!;
<$fh>;
};

Joomla 3: selecting multiple custom user fields into one html table

Forgive me - pretty much a Joomla/SQL rookie and trying to navigate through some tasks I trying to help my local home owners association with.
I'm looking for a way to build my own user list containing multiple custom user fields. My current query gives me multiple records for each user because each user is linked to multiple fields in the "__fields_values" table. I need only ONE record for each user and each custom field as a seperate value in this row.
A simple group clause doesn't seem to cut it.
Nevermind the actual table html, that's just for testing right now.
Hope someone can help me see the light :)
Now I get:
username1|field1|<blank>|email
username1|field2|<blank>|email
My table should look like:
username1|field1|field2|email
My current query and output:
$query = $db->getQuery(true);
$query
->select('*')
->from($db->quoteName('#__users', 'u'))
->join('INNER', $db->quoteName('#__user_usergroup_map', 'm') . ' ON (' . $db->quoteName('u.id') . ' = ' . $db->quoteName('m.user_id') . ')')
->join('INNER', $db->quoteName('#__fields_values', 'f') . ' ON (' . $db->quoteName('u.id') . ' = ' . $db->quoteName('f.item_id') . ')')
->where($db->quoteName('group_id') . ' = ' . $group_id)
->order($db->quoteName('u.username') . ' ASC')
$db->setQuery($query);
$users = $db->loadObjectList();
And then output to this table:
<table style="width:100%">
<tr style="border-bottom:1pt solid black;text-align: left;">
<th>Name</th>
<th>CustomField1</th>
<th>CustomField2</th>
<th>Email</th>
</tr>
<?php
foreach($users AS $user)
{
?>
<tr>
<td><?php;
echo $user->name;
?></td>
</td>
<td><?php;
echo $user->value;
?></td>
<td><?php;
echo $user->NEED ANOTHER VALUE HERE;
?></td>
<td><?php;
echo $user->email;
}?>
</table>
Probably You can do something like this to concatenate the result. If you are not getting the exact result you can just play with the code for what result you want. Your fields will be in the field array.
I have used CONCAT and GROUP_CONCAT. And you can have a look at it here https://www.w3resource.com/mysql/aggregate-functions-and-grouping/aggregate-functions-and-grouping-group_concat.php
$query = $db->getQuery(true)
->select(
array(
'*',
"CONCAT('[',GROUP_CONCAT(".$db->quoteName('f.value')."),']') field"
)
)
->from($db->quoteName('#__users', 'u'))
->leftJoin($db->quoteName('#__user_usergroup_map', 'm') . ' ON (' . $db->quoteName('u.id') . ' = ' . $db->quoteName('m.user_id'). ')')
->leftJoin($db->quoteName('#__fields_values', 'f') . ' ON (' . $db->quoteName('u.id') . ' = ' . $db->quoteName('f.item_id') . ')')
->where($db->quoteName('group_id') . ' = ' . $group_id);
$db->setQuery($query);
$users = $db->loadObjectList();
This will result in a singly array which you can do a var_dump() and check for yourself.

Wordpress admin - Where in database is it set?

I'm looking to grab admin user emails to use within a contact form. I have 2 admins that I've assigned. I'd like to grab them from the database. Where is/what is the designation point that I can use when I make the sql statment?
You can do the following
global $wpdb;
//comma separated list
$admins=$wpdb->get_var('select group_concat(`user_email`) as `admin_emails` from `' . $wpdb->prefix . 'users` as `users` inner join `' . $wpdb->prefix . 'usermeta` as `usermeta` on `usermeta`.`user_id`=`users`.`ID` where `meta_key`=\'wp_user_level\' and `meta_value` in (8,9,10);');
//array of associated arrays
$admins=$wpdb->get_results('select `user_email` from `' . $wpdb->prefix . 'users` as `users` inner join `' . $wpdb->prefix . 'usermeta` as `usermeta` on `usermeta`.`user_id`=`users`.`ID` where `meta_key`=\'wp_user_level\' and `meta_value` in (8,9,10);', ARRAY_A);
<?php $user_info = get_userdata(1);
echo 'Username: ' . $user_info->user_login . "\n";
echo 'User roles: ' . implode(', ', $user_info->roles) . "\n";
echo 'User ID: ' . $user_info->ID . "\n";
?>
You can pass the User id herer.....
The first thing to do is to create the function. To do so, paste the following code in your functions.php file:
function getUsersByRole($role) {
$wp_user_search = new WP_User_Search($usersearch, $userspage, $role);
return $wp_user_search->get_results();
}
Once done, you can call the function this way:
$editors = getUsersByRole('Administrator');
foreach($editors as $editor){
//$editor now holds the user ID of an editor
}

PHPExcel drawing new lines when combining sheets

I'm combining about 20 excel sheets (user uploaded) using PHPExcel into a report. This is done by using this bit of code:
$filename = APP . 'docs' . DS . 'reports' . DS . $Workbooks[0]['Report']['company'] . '.' . $Workbooks[0]['Report']['report_name'] . '.' . $Workbooks[0]['Report']['extension'];
$blacklist = array('Company Organogram');
$MasterFile = $this->PhpExcel->createMasterFile($filename,$company . '.' . $title,$colour);
foreach($Workbooks as $Workbook) :
if(!in_array($Workbook['Report']['report_name'],$blacklist)) {
$file = APP . 'docs' . DS . 'reports' . DS . $Workbook['Report']['company'] . '.' . $Workbook['Report']['report_name'] . '.' . $Workbook['Report']['extension'];
$MasterFile = $this->PhpExcel->addExternalWorksheet($MasterFile,$file,$company . '.' . $title,$colour);
#unlink($file);
}
endforeach;
$this->PhpExcel->saveToDisk(APP . 'docs' . DS . 'reports' . DS . 'Weekly Reports for Week ' . (date('W') + 1) . '.xlsx',$MasterFile);
I'm working with CakePHP, so there is a helper. saveToDisk simply saves the file to the disc after which it is attached and sent to a mailing list.
All the above works fine. But I'm having issues where the combining process draws in extra lines. For instance, this:
becomes this:
How would I fix this? Is there something I should set so it doesn't draw in all the lines?

Resources