Sphinx wildcard match on realtime index - real-time

I have created realtime index:
index berni_filter2
{
rt_mem_limit = 512M
type = rt
path = /var/lib/sphinxsearch/data/berni_filter
rt_attr_uint = product_id
rt_attr_uint = store_id
rt_field = product_name
rt_attr_json = attributes
prefix_fields = product_name
expand_keywords = 1
min_infix_len = 2
dict = keywords
}
Then I trying to get data by product name field over SphinxQL:
SELECT product_id FROM berni_filter2 WHERE store_id = 0 AND MATCH ('#product_name mothercare')
This query work fine, but I need to find partically words, for example "mother" must return products with "mothercare". I have tried:
SELECT product_id FROM berni_filter2 WHERE store_id = 0 AND MATCH ('#product_name mother')
SELECT product_id FROM berni_filter2 WHERE store_id = 0 AND MATCH ('#product_name mother*')
SELECT product_id FROM berni_filter2 WHERE store_id = 0 AND MATCH ('#product_name *mother*')
I tried change min_infix_len to min_prefix_len. Nothing work.

My mistake was, that I don't delete data files from filesystem, when change config, this is final working config:
index berni_filter
{
rt_mem_limit = 512M
type = rt
path = /var/lib/sphinxsearch/data/berni_filter
rt_attr_uint = product_id
rt_attr_uint = store_id
rt_field = product_name
rt_attr_json = attributes
index_exact_words = 1
expand_keywords = 1
min_prefix_len = 3
min_word_len = 2
morphology = stem_enru
dict = keywords
}

I faced the same problem. Deleting the index files helps me too.
Before deleting I stop the searchd service and then restart it.

Related

Efficient way to conditionally update values in 2 records in PostgreSQL

I have a table that contains 4 columns
id | category | score | enabled
1 | news | 95 | t
id -- serial
category -- varchar
score -- float
enabled -- bool
I want to update enabled to False if there's another record with a higher score.
For example, if I have:
id | category | score | enabled
1 | news | 95 | t
Then, after some operation, a new record with the same category is inserted:
id | category | score | enabled
1 | news | 95 | t
2 | news | 100 | f
Since the score for id=2 is higher, I want to change enabled for id=2 to True and change enabled for id=1 to False.
I'm wondering if I can combine these operations into 1 query. Right now I do 2 SELECT queries to get the 2 records, then compare the scores locally, and then change the enabled value (if needed).
So simply,
SELECT id, score
FROM table
WHERE category = %s
AND enabled = True
SELECT id, score
FROM table
WHERE category = %s
AND id = (SELECT max(id) WHERE category=%s)
if score2>= score1:
UPDATE table SET enabled = True
WHERE id = id2
UPDATE table SET enabled = False
WHERE id = id1
It works, but it seems very inefficient. Any way to improve these queries?
You can do that with a single update:
update the_table
set enabled = (score = t.max_score)
from (
select id, category, max(score) over (partition by category) as max_score
from the_table
where category = 'news'
) t
where t.id = the_table.id
and t.category = the_table.category;
This will set the enabled flags for all rows with the same category in a single statement.
Online example: https://rextester.com/DXR80618
If you happen to have more than one row with the same highest score for one category, the above statement will change enabled to true for all of, .
E.g.
id | category | score
---+----------+------
1 | news | 95
2 | news | 100
3 | news | 100
If you don't want that, and e.g. always pick the one with the lowest id to be the enabled row, you can use the following:
update the_table
set enabled = (rn = 1)
from (
select id, category,
row_number() over (partition by category order by score desc, id) as rn
from the_table
where category = 'news'
) t
where t.id = the_table.id
and t.category = the_table.category;
Online example: https://rextester.com/JPA61125

How to remove programmatically all participation of a student in a Moodle 2.5 group?

I need to remove an user programmatically from everything he is related with a group, like notes and everything. I removed the user from the table mdl_user_enrollments but he's still enrolled and when he logs in all data of the group is still being displayed. I want to remove everything this user has related with the group, so i can enroll he again and he'll start all over.
Don't know if this is exactly what you are looking for but the procedure bellow removes users data from course. Not from all installed moodle modules that will vary for each Moodle configuration) but you can add a few querys for your extra modules as well.
CREATE DEFINER = `your_user`#`%` PROCEDURE `RemoveUserDataFromCourse`(IN `c_id` int,IN `u_id` int)
BEGIN
# ENROLLMENT
DELETE FROM mdl_user_enrolments WHERE userid = u_id AND enrolid IN (SELECT id FROM mdl_enrol WHERE courseid = c_id);
# LOG, EVENT, POSTS
DELETE FROM mdl_log WHERE course = c_id AND userid = u_id;
DELETE FROM mdl_event WHERE courseid = c_id AND userid = u_id;
DELETE FROM mdl_post WHERE courseid = c_id AND userid = u_id;
# Course completion
DELETE FROM mdl_course_modules_completion WHERE coursemoduleid IN (SELECT id FROM mdl_course_modules WHERE course= c_id and userid=u_id);
DELETE FROM mdl_course_completions WHERE course = c_id AND userid = u_id;
DELETE FROM mdl_course_completion_crit_compl WHERE course = c_id AND userid = u_id;
# Grades from all modules
DELETE FROM mdl_grade_grades WHERE userid = u_id and itemid IN (SELECT id FROM mdl_grade_items WHERE courseid = c_id);
# MODULES
# ASSIGNMENTS
DELETE FROM mdl_assign_grades WHERE userid = u_id AND assignment IN (SELECT id FROM mdl_assign WHERE course = c_id);
# QUIZ
DELETE FROM mdl_quiz_attempts WHERE userid = u_id AND quiz IN (SELECT id FROM mdl_quiz WHERE course = c_id);
DELETE FROM mdl_quiz_grades WHERE userid = u_id AND quiz IN (SELECT id FROM mdl_quiz WHERE course = c_id);
# SCORM
DELETE FROM mdl_scorm_scoes_track WHERE userid = u_id AND scormid IN (SELECT id FROM mdl_scorm WHERE course = c_id);
# CHECK LIST
DELETE FROM mdl_checklist_check WHERE userid = u_id AND item IN ( SELECT mci.id FROM mdl_checklist mc INNER JOIN mdl_checklist_item mci ON mci.checklist = mc.id WHERE course = c_id );
DELETE FROM mdl_checklist_comment WHERE userid = u_id AND itemid IN ( SELECT mci.id FROM mdl_checklist mc INNER JOIN mdl_checklist_item mci ON mci.checklist = mc.id WHERE course = c_id );
# CHOICE
DELETE FROM mdl_choice_answers WHERE userid = u_id AND choiceid IN (SELECT id FROM mdl_choice WHERE course = c_id);
END;
This procedure is based on the operations made by course/reset.php it receives two parameters: the course id and the user id. Add/remove the modules related querys depending on you Moodle configuration.

Sphinx search by attribute

Could I search with sphinx only by attributes without query word
config:
sql_query = SELECT p.ID as price_id, p.info, p.sort_id, p.made_id, p.category_id, 'prices' as table_id FROM price AS p
sql_query_info = SELECT * FROM price WHERE ID = $id
sql_attr_uint = sort_id
...
min_word_len = 0
min_infix_len = 0
min_prefix_len = 0
enable_star = 1
docinfo = extern
code:
$search->SetFilter('sort_id',[1,2]);
$search->Query("*","prices");
Get 0 results
$search->Query("","prices");
If that returns no results, you've got some other logic error.
Tangential, why are you 'enable_star' with infix/prefix set to 0? It will have no effect.

Sphinx empty index

I'm trying to create index from table domains. When I get 10 attributes, everything is ok. When i add 11-th, indexer returns:
collected 1629494 docs, 0.0 MB
Config:
#...
sql_attr_uint = did
sql_attr_string = url
sql_attr_uint = zone_id
sql_attr_uint = first_letter
sql_attr_uint = category_id
sql_attr_uint = is_parking
#sql_attr_uint = data3
sql_attr_uint = views
sql_attr_uint = data1
sql_attr_uint = data2
sql_attr_uint = is_top_site
#...
When I remove any of the 11 attributes, everything works fine. Is there some kind of limit ?

sql server update many columns with a select from a join of a table variable and a db table

I have the classical person -> person attributes scheme.
So, like this: person(PK) <- person_attribute(FK)
What I need is a query to get one row where a person is joined with her attributes.
For example, to transform:
Person:
{ ID = 123456, Name = 'John Smith', Age = 25 }
Attributes:
1) { PersonID = 123456, AttributeTypeID = 'Height', AttributeValue = '6'6'''}
2) { PersonID = 123456, AttributeTypeID = 'Weight', AttributeValue = '220lbs'}
3) { PersonID = 123456, AttributeTypeID = 'EyeColor', AttributeValue = 'Blue'}
To:
PersonWithAttributes
{
ID = 123456, Name = 'John Smith', Age = 25, Height = '6'6''', Weight = '220lbs', EyeColor = 'Blue'
}
To make things worse my persons are in a table variable.
So, I have (in a sp with a parameter of person_id):
--result table
declare #people_info table
(
person_id int,
name nvarchar(max),
age int,
height nvarchar(10) null,
weight nvarchar(10) null,
eye_color nvarchar(16) null
)
insert into #people_info
select person_id, name, age, null, null, null
from dbo.HR.people where person_id = #person_id
update pi
set
pi.height = (select pa.attribute_value where pa.attribute_type_id = 'Height'),
pi.height = (select pa.attribute_value where pa.attribute_type_id = 'Weight'),
pi.eye_color = (select pa.attribute_value where pa.attribute_type_id = 'EyeColor')
from
#people_info pi
inner join dbo.HR.person_attributes pa on pi.person_id = pa.person_id
select * from #people_info
Which of course does not work for some reason.
If I query the two joined tables and select "pa.attribute_value where pa.attribute_type_id = 'someval'" I get the correct value. But the update does not work.
Of course, I can write this as three updates, but I am thinking that it will be faster to do one join and then to filter in the update clause.
Also, please keep in mind that my attributes are spread over three tables, not just the attributes table. So, this is why I have the table variable.
Any help is very welcome. Maybe I am going about this the wrong way. Performance matters. What is the most performant way to accomplish this?
Thank you very much.
Try this code for update with pivot:
update
pi
set
pi.height = pa.Height
pi.weight = pa.Weight
pi.eye_color = pa.EyeColor
from
#people_info pi
inner join
(
SELECT
person_id
,[Height] Height
,[Weight] Weight
,[EyeColor] EyeColor
FROM
(
SELECT
attribute_type_id
, attribute_value
, person_id
FROM
dbo.HR.person_attributes pa
) pa
PIVOT
(
MAX(attribute_value) FOR attribute_type_id IN ([Height],[Weight],[EyeColor])
)pvt
) pa
on
pi.person_id = pa.person_id
Maybe you want something like:
update pi
set
pi.height = paH.attribute_value,
pi.weight = paW.attribute_value,
pi.eye_color = paE.attribute_value
from
#people_info pi
inner join dbo.HR.person_attributes paH on pi.person_id = paH.person_id
and paH.attribute_type_id = 'Height'
inner join dbo.HR.person_attributes paW on pi.person_id = paW.person_id
and paW.attribute_type_id = 'Weight'
inner join dbo.HR.person_attributes paE on pi.person_id = paE.person_id
and paE.attribute_type_id = 'EyeColor'