SlideShare a Scribd company logo
1 of 45
Download to read offline
Dive into
full text search
with Python
Andrii Soldatenko
18-19 September 2015
@a_soldatenko
About me:
• Lead QA Automation Engineer at
• Backend Python Developer at
• Speaker at PyCon Ukraine 2014
• Speaker at PyCon Belarus 2015
• @a_soldatenko
Preface
Information Explosion
Text Search
grep	
  -­‐-­‐ignore-­‐case	
  -­‐-­‐recursive	
  foo	
  books/	
  
grep	
  -­‐-­‐ignore-­‐case	
  -­‐-­‐recursive	
  -­‐-­‐file=words.txt	
  books/
Entry.objects.get(headline__icontains='foo')	
  
words	
  =	
  []	
  
with	
  open('words.txt',	
  'r')	
  as	
  f:	
  
	
  	
  	
  	
  words	
  =	
  f.readlines()	
  
Entry.objects.get(headline__icontains_in=words)
Full text search
Search index
Simple sentences
1. The quick brown fox jumped over the lazy dog
2. Quick brown foxes leap over lazy dogs in summer
Inverted index
Term	
  	
  	
  	
  	
  	
  Doc_1	
  	
  Doc_2	
  
-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐	
  
Quick	
  	
  	
  |	
  	
  	
  	
  	
  	
  	
  |	
  	
  X	
  
The	
  	
  	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  
brown	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  	
  X	
  
dog	
  	
  	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  
dogs	
  	
  	
  	
  |	
  	
  	
  	
  	
  	
  	
  |	
  	
  X	
  
fox	
  	
  	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  
foxes	
  	
  	
  |	
  	
  	
  	
  	
  	
  	
  |	
  	
  X	
  
in	
  	
  	
  	
  	
  	
  |	
  	
  	
  	
  	
  	
  	
  |	
  	
  X	
  
jumped	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  
lazy	
  	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  	
  X	
  
leap	
  	
  	
  	
  |	
  	
  	
  	
  	
  	
  	
  |	
  	
  X	
  
over	
  	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  	
  X	
  
quick	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  
summer	
  	
  |	
  	
  	
  	
  	
  	
  	
  |	
  	
  X	
  
the	
  	
  	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  
-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐
Inverted index
Term	
  	
  	
  	
  	
  	
  Doc_1	
  	
  Doc_2	
  
-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐	
  
brown	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  	
  X	
  
quick	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  
-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐	
  
Total	
  	
  	
  |	
  	
  	
  2	
  	
  	
  |	
  	
  1
Inverted index:
normalization
Term	
  	
  	
  	
  	
  	
  Doc_1	
  	
  Doc_2	
  
-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐	
  
brown	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  	
  X	
  
dog	
  	
  	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  	
  X	
  
fox	
  	
  	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  	
  X	
  
in	
  	
  	
  	
  	
  	
  |	
  	
  	
  	
  	
  	
  	
  |	
  	
  X	
  
jump	
  	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  	
  X	
  
lazy	
  	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  	
  X	
  
over	
  	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  	
  X	
  
quick	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  	
  X	
  
summer	
  	
  |	
  	
  	
  	
  	
  	
  	
  |	
  	
  X	
  
the	
  	
  	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  	
  X	
  
-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐
Term	
  	
  	
  	
  	
  	
  Doc_1	
  	
  Doc_2	
  
-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐	
  
Quick	
  	
  	
  |	
  	
  	
  	
  	
  	
  	
  |	
  	
  X	
  
The	
  	
  	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  
brown	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  	
  X	
  
dog	
  	
  	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  
dogs	
  	
  	
  	
  |	
  	
  	
  	
  	
  	
  	
  |	
  	
  X	
  
fox	
  	
  	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  
foxes	
  	
  	
  |	
  	
  	
  	
  	
  	
  	
  |	
  	
  X	
  
in	
  	
  	
  	
  	
  	
  |	
  	
  	
  	
  	
  	
  	
  |	
  	
  X	
  
jumped	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  
lazy	
  	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  	
  X	
  
leap	
  	
  	
  	
  |	
  	
  	
  	
  	
  	
  	
  |	
  	
  X	
  
over	
  	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  	
  X	
  
quick	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  
summer	
  	
  |	
  	
  	
  	
  	
  	
  	
  |	
  	
  X	
  
the	
  	
  	
  	
  	
  |	
  	
  	
  X	
  	
  	
  |	
  
-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐
Search Engines
PostgreSQL
PostgreSQL:

operators for textual data types
-­‐-­‐-­‐	
  PostgreSQL	
  has	
  operators	
  for	
  textual	
  data	
  types:	
  
-­‐-­‐-­‐	
  LIKE	
  -­‐	
  match	
  case-­‐sensitive	
  
-­‐-­‐-­‐	
  ILIKE	
  -­‐	
  match	
  case-­‐insensitive	
  
-­‐-­‐-­‐	
  ~	
  -­‐	
  Matches	
  POSIX	
  regular	
  expression,	
  case-­‐sensitive	
  
-­‐-­‐-­‐	
  ~*	
  -­‐	
  Matches	
  POSIX	
  regular	
  expression,	
  case-­‐insensitive	
  
select	
  'foo'	
  LIKE	
  'foo';	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐-­‐	
  true	
  
select	
  'bar'	
  ILIKE	
  'BAR';	
  	
  	
  	
  	
  	
  	
  	
  -­‐-­‐	
  true	
  	
  
select	
  'abc'	
  LIKE	
  'b';	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐-­‐	
  true	
  
select	
  'abc'	
  LIKE	
  'c';	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐-­‐	
  false	
  
select	
  'abc'	
  ~	
  'abc';	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐-­‐	
  true	
  
select	
  'abc'	
  ~	
  '^a';	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐-­‐	
  true	
  
select	
  'abc'	
  ~	
  '(b|d)';	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐-­‐	
  true	
  
select	
  'abc'	
  ~	
  '^(b|c)';	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐-­‐	
  false	
  
select	
  'andrii'	
  ~*	
  '.*Andrii.*';	
  -­‐-­‐	
  true
PostgreSQL:

accuracy issue
select	
  'prone'	
  like	
  '%one%';	
  -­‐-­‐true	
  	
  
select	
  'money'	
  like	
  '%one%';	
  -­‐-­‐true	
  	
  
select	
  'lonely'	
  like	
  '%one%';	
  -­‐-­‐true	
  	
  
Full text search in
PostgreSQL
1.Creating tokens
2.Creating Lexems (Normaliztion)
3.storing preprocessed documents
4.Relevance ranking
Full text search in
PostgreSQL
27 built-in configurations for 10 languages
Support of user-defined FTS configurations
Pluggable dictionaries, parsers
Inverted indexes
functions to convert
normal text to tsvector
explain	
  SELECT	
  'a	
  fat	
  cat	
  sat	
  on	
  a	
  mat	
  and	
  ate	
  a	
  fat	
  rat'::tsvector	
  @@	
  	
  
	
  	
  	
  	
  	
  	
  	
  'cat	
  &	
  rat’::tsquery;	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  QUERY	
  PLAN	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐	
  
	
  Result	
  	
  (cost=0.00..0.01	
  rows=1	
  width=0)	
  
(1	
  row)	
  
explain	
  SELECT	
  'fat	
  &	
  cow'::tsquery	
  @@	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  'a	
  fat	
  cat	
  sat	
  on	
  a	
  mat	
  and	
  ate	
  a	
  fat	
  rat'::tsvector;	
  -­‐-­‐	
  false	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  QUERY	
  PLAN	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐	
  
	
  Result	
  	
  (cost=0.00..0.01	
  rows=1	
  width=0)	
  
(1	
  row)
PostgreSQL:

index management
CREATE	
  FUNCTION	
  notes_vector_update()	
  RETURNS	
  TRIGGER	
  AS	
  $$	
  
BEGIN	
  
	
  	
  	
  	
  IF	
  TG_OP	
  =	
  'INSERT'	
  THEN	
  
	
  	
  	
  	
  	
  	
  	
  	
  new.search_index	
  =	
  to_tsvector('pg_catalog.english',	
  COALESCE(NEW.name,	
  ''));	
  
	
  	
  	
  	
  END	
  IF;	
  
	
  	
  	
  	
  IF	
  TG_OP	
  =	
  'UPDATE'	
  THEN	
  
	
  	
  	
  	
  	
  	
  	
  	
  IF	
  NEW.name	
  <>	
  OLD.name	
  THEN	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  new.search_index	
  =	
  to_tsvector('pg_catalog.english',	
  COALESCE(NEW.name,	
  ''));	
  
	
  	
  	
  	
  	
  	
  	
  	
  END	
  IF;	
  
	
  	
  	
  	
  END	
  IF;	
  
	
  	
  	
  	
  RETURN	
  NEW;	
  
END	
  
$$	
  LANGUAGE	
  'plpgsql';	
  
PostgreSQL:

stopwords
SELECT	
  to_tsvector('english','in	
  the	
  list	
  of	
  stop	
  words');	
  
	
  	
  	
  	
  	
  	
  	
  to_tsvector	
  
-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐	
  
	
  'list':3	
  'stop':5	
  'word':6
/usr/pgsql-9.3/share/tsearch_data/english.stop
Django:
PostgreSQL full-text search
integration with django orm
https://github.com/linuxlewis/djorm-ext-pgfulltext
from	
  djorm_pgfulltext.models	
  import	
  SearchManager	
  
from	
  djorm_pgfulltext.fields	
  import	
  VectorField	
  
from	
  django.db	
  import	
  models	
  
class	
  Page(models.Model):	
  
	
  	
  	
  	
  name	
  =	
  models.CharField(max_length=200)	
  
	
  	
  	
  	
  description	
  =	
  models.TextField()	
  
	
  	
  	
  	
  search_index	
  =	
  VectorField()	
  
	
  	
  	
  	
  objects	
  =	
  SearchManager(	
  
	
  	
  	
  	
  	
  	
  	
  	
  fields	
  =	
  ('name',	
  'description'),	
  
	
  	
  	
  	
  	
  	
  	
  	
  config	
  =	
  'pg_catalog.english',	
  #	
  this	
  is	
  default	
  
	
  	
  	
  	
  	
  	
  	
  	
  search_field	
  =	
  'search_index',	
  #	
  this	
  is	
  default	
  
	
  	
  	
  	
  	
  	
  	
  	
  auto_update_search_field	
  =	
  True	
  
	
  	
  	
  	
  )
For search just use search
method of the manager
https://github.com/linuxlewis/djorm-ext-pgfulltext
>>>	
  Page.objects.search("documentation	
  &	
  about")	
  
[<Page:	
  Page:	
  Home	
  page>]	
  
>>>	
  Page.objects.search("about	
  |	
  documentation	
  |	
  django	
  |	
  home",	
  raw=True)	
  
[<Page:	
  Page:	
  Home	
  page>,	
  <Page:	
  Page:	
  About>,	
  <Page:	
  Page:	
  Navigation>]
Second way
class	
  Page(models.Model):	
  
	
  	
  	
  	
  name	
  =	
  models.CharField(max_length=200)	
  
	
  	
  	
  	
  description	
  =	
  models.TextField()	
  
	
  	
  	
  	
  objects	
  =	
  SearchManager(fields=None,	
  search_field=None)	
  
>>>	
  Page.objects.search("documentation	
  &	
  about",	
  fields=('name',	
  
'description'))	
  
[<Page:	
  Page:	
  Home	
  page>]	
  
>>>	
  Page.objects.search("about	
  |	
  documentation	
  |	
  django	
  |	
  home",	
  
raw=True,	
  fields=('name',	
  'description'))	
  
[<Page:	
  Page:	
  Home	
  page>,	
  <Page:	
  Page:	
  About>,	
  <Page:	
  Page:	
  
Navigation>]
Pros and Cons
Pros:
• Quick implementation
• No dependency
Cons:
• Need manually manage indexes
• Not as flexible as pure search engines
• Not so fast as ElasticSearch
• tied to PostgreSQL
• no analytics data
• no DSL only `&` and `|` queries
• difficult to manage stop words
ElasticSearch
Who uses ElasticSearch?
ElasticSearch:
Quick Intro
Relational DB Databases TablesRows Columns
ElasticSearch Indices FieldsTypes Documents
ElasticSearch:
Locks
•Pessimistic concurrency control
•Optimistic concurrency control
ElasticSearch:
Setup
#!/bin/bash	
  
VERSION=1.7.1	
  
curl	
  -­‐L	
  -­‐O	
  https://download.elastic.co/elasticsearch/elasticsearch/
elasticsearch-­‐$VERSION.zip	
  
unzip	
  elasticsearch-­‐$VERSION.zip	
  
cd	
  elasticsearch-­‐$VERSION	
  
#	
  Download	
  plugin	
  marvel	
  
./bin/plugin	
  -­‐i	
  elasticsearch/marvel/latest	
  
echo	
  'marvel.agent.enabled:	
  false'	
  >>	
  ./config/elasticsearch.yml	
  
#	
  run	
  elastic	
  
./bin/elasticsearch	
  -­‐d
ElasticSearch:
Setup
$	
  curl	
  ‘http://localhost:9200/?pretty'	
  
{	
  
	
  	
  "status"	
  :	
  200,	
  
	
  	
  "name"	
  :	
  "Dredmund	
  Druid",	
  
	
  	
  "cluster_name"	
  :	
  "elasticsearch",	
  
	
  	
  "version"	
  :	
  {	
  
	
  	
  	
  	
  "number"	
  :	
  "1.7.1",	
  
	
  	
  	
  	
  "build_hash"	
  :	
  "b88f43fc40b0bcd7f173a1f9ee2e97816de80b19",	
  
	
  	
  	
  	
  "build_timestamp"	
  :	
  "2015-­‐07-­‐29T09:54:16Z",	
  
	
  	
  	
  	
  "build_snapshot"	
  :	
  false,	
  
	
  	
  	
  	
  "lucene_version"	
  :	
  "4.10.4"	
  
	
  	
  },	
  
	
  	
  "tagline"	
  :	
  "You	
  Know,	
  for	
  Search"	
  
}
Haystack
Adding search functionality
to Simple Model
$	
  cat	
  myapp/models.py	
  
from	
  django.db	
  import	
  models	
  
from	
  django.contrib.auth.models	
  import	
  User	
  
class	
  Page(models.Model):	
  
	
  	
  	
  	
  user	
  =	
  models.ForeignKey(User)	
  
	
  	
  	
  	
  name	
  =	
  models.CharField(max_length=200)	
  
	
  	
  	
  	
  description	
  =	
  models.TextField()	
  
	
  	
  	
  	
  def	
  __unicode__(self):	
  
	
  	
  	
  	
  	
  	
  	
  	
  return	
  self.name	
  
Haystack: Installation
$	
  pip	
  install	
  django-­‐haystack	
  
$	
  cat	
  settings.py	
  
INSTALLED_APPS	
  =	
  [	
  
	
  	
  	
  	
  'django.contrib.admin',	
  
	
  	
  	
  	
  'django.contrib.auth',	
  
	
  	
  	
  	
  'django.contrib.contenttypes',	
  
	
  	
  	
  	
  'django.contrib.sessions',	
  
	
  	
  	
  	
  'django.contrib.sites',	
  
	
  	
  	
  	
  #	
  Added.	
  
	
  	
  	
  	
  'haystack',	
  
	
  	
  	
  	
  #	
  Then	
  your	
  usual	
  apps...	
  
	
  	
  	
  	
  'blog',	
  
]
Haystack: Installation
$	
  pip	
  install	
  elasticsearch	
  
$	
  cat	
  settings.py	
  
...	
  
HAYSTACK_CONNECTIONS	
  =	
  {	
  
	
  	
  	
  	
  'default':	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  'ENGINE':	
  
'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',	
  
	
  	
  	
  	
  	
  	
  	
  	
  'URL':	
  'http://127.0.0.1:9200/',	
  
	
  	
  	
  	
  	
  	
  	
  	
  'INDEX_NAME':	
  'haystack',	
  
	
  	
  	
  	
  },	
  
}	
  
...
Haystack:
Creating SearchIndexes
$	
  cat	
  myapp/search_indexes.py	
  
import	
  datetime	
  
from	
  haystack	
  import	
  indexes	
  
from	
  myapp.models	
  import	
  Note	
  
class	
  PageIndex(indexes.SearchIndex,	
  indexes.Indexable):	
  
	
  	
  	
  	
  text	
  =	
  indexes.CharField(document=True,	
  use_template=True)	
  
	
  	
  	
  	
  author	
  =	
  indexes.CharField(model_attr='user')	
  
	
  	
  	
  	
  pub_date	
  =	
  indexes.DateTimeField(model_attr='pub_date')	
  
	
  	
  	
  	
  def	
  get_model(self):	
  
	
  	
  	
  	
  	
  	
  	
  	
  return	
  Note	
  
	
  	
  	
  	
  def	
  index_queryset(self,	
  using=None):	
  
	
  	
  	
  	
  	
  	
  	
  	
  """Used	
  when	
  the	
  entire	
  index	
  for	
  model	
  is	
  updated."""	
  
	
  	
  	
  	
  	
  	
  	
  	
  return	
  self.get_model().objects.	
  	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  filter(pub_date__lte=datetime.datetime.now())
Haystack:
SearchQuerySet API
from	
  haystack.query	
  import	
  SearchQuerySet	
  
from	
  haystack.inputs	
  import	
  Raw	
  
all_results	
  =	
  SearchQuerySet().all()	
  
hello_results	
  =	
  SearchQuerySet().filter(content='hello')	
  
unfriendly_results	
  =	
  SearchQuerySet().	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  exclude(content=‘hello’).	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  filter(content=‘world’)	
  
#	
  To	
  send	
  unescaped	
  data:	
  
sqs	
  =	
  SearchQuerySet().filter(title=Raw(trusted_query))	
  
Keeping data in sync
#	
  Update	
  everything.	
  
./manage.py	
  update_index	
  -­‐-­‐settings=settings.prod	
  
#	
  Update	
  everything	
  with	
  lots	
  of	
  information	
  about	
  what's	
  going	
  on.	
  
./manage.py	
  update_index	
  -­‐-­‐settings=settings.prod	
  -­‐-­‐verbosity=2	
  
#	
  Update	
  everything,	
  cleaning	
  up	
  after	
  deleted	
  models.	
  
./manage.py	
  update_index	
  -­‐-­‐remove	
  -­‐-­‐settings=settings.prod	
  
#	
  Update	
  everything	
  changed	
  in	
  the	
  last	
  2	
  hours.	
  
./manage.py	
  update_index	
  -­‐-­‐age=2	
  -­‐-­‐settings=settings.prod	
  
#	
  Update	
  everything	
  between	
  Dec.	
  1,	
  2011	
  &	
  Dec	
  31,	
  2011	
  
./manage.py	
  update_index	
  -­‐-­‐start='2011-­‐12-­‐01T00:00:00'	
  -­‐-­‐
end='2011-­‐12-­‐31T23:59:59'	
  -­‐-­‐settings=settings.prod
Signals
class	
  RealtimeSignalProcessor(BaseSignalProcessor):	
  
	
  	
  	
  	
  """	
  
	
  	
  	
  	
  Allows	
  for	
  observing	
  when	
  saves/deletes	
  fire	
  &	
  automatically	
  updates	
  the	
  
	
  	
  	
  	
  search	
  engine	
  appropriately.	
  
	
  	
  	
  	
  """	
  
	
  	
  	
  	
  def	
  setup(self):	
  
	
  	
  	
  	
  	
  	
  	
  	
  #	
  Naive	
  (listen	
  to	
  all	
  model	
  saves).	
  
	
  	
  	
  	
  	
  	
  	
  	
  models.signals.post_save.connect(self.handle_save)	
  
	
  	
  	
  	
  	
  	
  	
  	
  models.signals.post_delete.connect(self.handle_delete)	
  
	
  	
  	
  	
  	
  	
  	
  	
  #	
  Efficient	
  would	
  be	
  going	
  through	
  all	
  backends	
  &	
  collecting	
  all	
  models	
  
	
  	
  	
  	
  	
  	
  	
  	
  #	
  being	
  used,	
  then	
  hooking	
  up	
  signals	
  only	
  for	
  those.	
  
	
  	
  	
  	
  def	
  teardown(self):	
  
	
  	
  	
  	
  	
  	
  	
  	
  #	
  Naive	
  (listen	
  to	
  all	
  model	
  saves).	
  
	
  	
  	
  	
  	
  	
  	
  	
  models.signals.post_save.disconnect(self.handle_save)	
  
	
  	
  	
  	
  	
  	
  	
  	
  models.signals.post_delete.disconnect(self.handle_delete)	
  
	
  	
  	
  	
  	
  	
  	
  	
  #	
  Efficient	
  would	
  be	
  going	
  through	
  all	
  backends	
  &	
  collecting	
  all	
  models	
  
	
  	
  	
  	
  	
  	
  	
  	
  #	
  being	
  used,	
  then	
  disconnecting	
  signals	
  only	
  for	
  those.
Haystack:
Pros and Cons
Pros:
• easy to setup
• looks like Django ORM but for searches
• search engine independent
• support 4 engines (Elastic, Solr, Xapian, Whoosh)
Cons:
• poor SearchQuerySet API
• difficult to manage stop words
• loose performance, because extra layer
• Model - based
Future FTS and
Roadmap Django 1.9
• PostgreSQL Full Text Search (Marc Tamlyn)
https://github.com/django/django/pull/4726
• Custom indexes (Marc Tamlyn)
• etc.
Final Thoughts
https://www.elastic.co/guide/en/elasticsearch/guide/master/
index.html
Questions
?
Thank You
a_soldatenko@wargaming.net
@a_soldatenko
https://asoldatenko.com
We are hiring
a_soldatenko@wargaming.net

More Related Content

Viewers also liked (8)

Seminario 3.
Seminario 3.Seminario 3.
Seminario 3.
 
Salon chairs toronto
Salon chairs torontoSalon chairs toronto
Salon chairs toronto
 
Unidad 2 cragomepeza
Unidad 2   cragomepezaUnidad 2   cragomepeza
Unidad 2 cragomepeza
 
General industry safety and health -osha 30 hrs
General industry safety and health -osha 30 hrsGeneral industry safety and health -osha 30 hrs
General industry safety and health -osha 30 hrs
 
HÁBITAT III BORRADOR CERO DE LA NUEVA AGENDA URBANA - 06 de mayo de el año 2016
HÁBITAT III BORRADOR CERO DE LA NUEVA AGENDA URBANA - 06 de mayo de el año 2016HÁBITAT III BORRADOR CERO DE LA NUEVA AGENDA URBANA - 06 de mayo de el año 2016
HÁBITAT III BORRADOR CERO DE LA NUEVA AGENDA URBANA - 06 de mayo de el año 2016
 
3° año guía 12 - comun los relativos
3° año   guía 12 - comun los relativos3° año   guía 12 - comun los relativos
3° año guía 12 - comun los relativos
 
Phase Transformation.
Phase Transformation.Phase Transformation.
Phase Transformation.
 
Труды Левановой Е. А.
Труды Левановой Е. А.Труды Левановой Е. А.
Труды Левановой Е. А.
 

Similar to Погружение в полнотекстовый поиск, используя Python - Андрей Солдатенко, Wargaming.NET

PyCon Russian 2015 - Dive into full text search with python.
PyCon Russian 2015 - Dive into full text search with python.PyCon Russian 2015 - Dive into full text search with python.
PyCon Russian 2015 - Dive into full text search with python.Andrii Soldatenko
 
PostgreSQL FTS Solutions FOSDEM 2013 - PGDAY
PostgreSQL FTS Solutions FOSDEM 2013 - PGDAYPostgreSQL FTS Solutions FOSDEM 2013 - PGDAY
PostgreSQL FTS Solutions FOSDEM 2013 - PGDAYEmanuel Calvo
 
Kernel Recipes 2019 - GNU poke, an extensible editor for structured binary data
Kernel Recipes 2019 - GNU poke, an extensible editor for structured binary dataKernel Recipes 2019 - GNU poke, an extensible editor for structured binary data
Kernel Recipes 2019 - GNU poke, an extensible editor for structured binary dataAnne Nicolas
 
Hvordan sette opp en OAI-PMH metadata-innhøster
Hvordan sette opp en OAI-PMH metadata-innhøsterHvordan sette opp en OAI-PMH metadata-innhøster
Hvordan sette opp en OAI-PMH metadata-innhøsterLibriotech
 
ELK-Stack-Essential-Concepts-TheELKStack-LunchandLearn.pdf
ELK-Stack-Essential-Concepts-TheELKStack-LunchandLearn.pdfELK-Stack-Essential-Concepts-TheELKStack-LunchandLearn.pdf
ELK-Stack-Essential-Concepts-TheELKStack-LunchandLearn.pdfcadejaumafiq
 
Tests unitaires pour PostgreSQL avec pgTap
Tests unitaires pour PostgreSQL avec pgTapTests unitaires pour PostgreSQL avec pgTap
Tests unitaires pour PostgreSQL avec pgTapRodolphe Quiédeville
 
UNIX SHELL IN DBA EVERYDAY
UNIX SHELL IN DBA EVERYDAYUNIX SHELL IN DBA EVERYDAY
UNIX SHELL IN DBA EVERYDAYSignis Vavere
 
pg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQLpg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQLCommand Prompt., Inc
 
pg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQLpg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQLMark Wong
 
An introduction to Raku
An introduction to RakuAn introduction to Raku
An introduction to RakuSimon Proctor
 
Internationalizing CakePHP Applications
Internationalizing CakePHP ApplicationsInternationalizing CakePHP Applications
Internationalizing CakePHP ApplicationsPierre MARTIN
 
Python interview questions
Python interview questionsPython interview questions
Python interview questionsPragati Singh
 
AWS Hadoop and PIG and overview
AWS Hadoop and PIG and overviewAWS Hadoop and PIG and overview
AWS Hadoop and PIG and overviewDan Morrill
 
Postgres performance for humans
Postgres performance for humansPostgres performance for humans
Postgres performance for humansCraig Kerstiens
 
Semantic Pipes (London Perl Workshop 2009)
Semantic Pipes (London Perl Workshop 2009)Semantic Pipes (London Perl Workshop 2009)
Semantic Pipes (London Perl Workshop 2009)osfameron
 

Similar to Погружение в полнотекстовый поиск, используя Python - Андрей Солдатенко, Wargaming.NET (20)

PyCon Russian 2015 - Dive into full text search with python.
PyCon Russian 2015 - Dive into full text search with python.PyCon Russian 2015 - Dive into full text search with python.
PyCon Russian 2015 - Dive into full text search with python.
 
Kyiv.py #16 october 2015
Kyiv.py #16 october 2015Kyiv.py #16 october 2015
Kyiv.py #16 october 2015
 
PostgreSQL FTS Solutions FOSDEM 2013 - PGDAY
PostgreSQL FTS Solutions FOSDEM 2013 - PGDAYPostgreSQL FTS Solutions FOSDEM 2013 - PGDAY
PostgreSQL FTS Solutions FOSDEM 2013 - PGDAY
 
Kernel Recipes 2019 - GNU poke, an extensible editor for structured binary data
Kernel Recipes 2019 - GNU poke, an extensible editor for structured binary dataKernel Recipes 2019 - GNU poke, an extensible editor for structured binary data
Kernel Recipes 2019 - GNU poke, an extensible editor for structured binary data
 
Hvordan sette opp en OAI-PMH metadata-innhøster
Hvordan sette opp en OAI-PMH metadata-innhøsterHvordan sette opp en OAI-PMH metadata-innhøster
Hvordan sette opp en OAI-PMH metadata-innhøster
 
ELK-Stack-Essential-Concepts-TheELKStack-LunchandLearn.pdf
ELK-Stack-Essential-Concepts-TheELKStack-LunchandLearn.pdfELK-Stack-Essential-Concepts-TheELKStack-LunchandLearn.pdf
ELK-Stack-Essential-Concepts-TheELKStack-LunchandLearn.pdf
 
Tests unitaires pour PostgreSQL avec pgTap
Tests unitaires pour PostgreSQL avec pgTapTests unitaires pour PostgreSQL avec pgTap
Tests unitaires pour PostgreSQL avec pgTap
 
UNIX SHELL IN DBA EVERYDAY
UNIX SHELL IN DBA EVERYDAYUNIX SHELL IN DBA EVERYDAY
UNIX SHELL IN DBA EVERYDAY
 
UNIX SHELL IN DBA EVERYDAY
UNIX SHELL IN DBA EVERYDAYUNIX SHELL IN DBA EVERYDAY
UNIX SHELL IN DBA EVERYDAY
 
Vegas ES
Vegas ESVegas ES
Vegas ES
 
Fuzzing - A Tale of Two Cultures
Fuzzing - A Tale of Two CulturesFuzzing - A Tale of Two Cultures
Fuzzing - A Tale of Two Cultures
 
pg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQLpg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQL
 
pg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQLpg_proctab: Accessing System Stats in PostgreSQL
pg_proctab: Accessing System Stats in PostgreSQL
 
An introduction to Raku
An introduction to RakuAn introduction to Raku
An introduction to Raku
 
Internationalizing CakePHP Applications
Internationalizing CakePHP ApplicationsInternationalizing CakePHP Applications
Internationalizing CakePHP Applications
 
Python interview questions
Python interview questionsPython interview questions
Python interview questions
 
Odp
OdpOdp
Odp
 
AWS Hadoop and PIG and overview
AWS Hadoop and PIG and overviewAWS Hadoop and PIG and overview
AWS Hadoop and PIG and overview
 
Postgres performance for humans
Postgres performance for humansPostgres performance for humans
Postgres performance for humans
 
Semantic Pipes (London Perl Workshop 2009)
Semantic Pipes (London Perl Workshop 2009)Semantic Pipes (London Perl Workshop 2009)
Semantic Pipes (London Perl Workshop 2009)
 

More from it-people

«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co
«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co
«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Coit-people
 
«Scrapy internals» Александр Сибиряков, Scrapinghub
«Scrapy internals» Александр Сибиряков, Scrapinghub«Scrapy internals» Александр Сибиряков, Scrapinghub
«Scrapy internals» Александр Сибиряков, Scrapinghubit-people
 
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrainsit-people
 
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
«Gevent — быть или не быть?» Александр Мокров, Positive Technologiesit-people
 
«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс
«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс
«Ещё один Поиск Яндекса» Александр Кошелев, Яндексit-people
 
«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...
«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...
«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...it-people
 
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalrit-people
 
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...it-people
 
«Тотальный контроль производительности» Михаил Юматов, ЦИАН
«Тотальный контроль производительности» Михаил Юматов, ЦИАН«Тотальный контроль производительности» Михаил Юматов, ЦИАН
«Тотальный контроль производительности» Михаил Юматов, ЦИАНit-people
 
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банкit-people
 
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Coit-people
 
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНСit-people
 
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...it-people
 
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologiesit-people
 
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn Systemit-people
 
«(Без)опасный Python», Иван Цыганов, Positive Technologies
«(Без)опасный Python», Иван Цыганов, Positive Technologies«(Без)опасный Python», Иван Цыганов, Positive Technologies
«(Без)опасный Python», Иван Цыганов, Positive Technologiesit-people
 
«Python of Things», Кирилл Борисов, Яндекс
«Python of Things», Кирилл Борисов, Яндекс«Python of Things», Кирилл Борисов, Яндекс
«Python of Things», Кирилл Борисов, Яндексit-people
 
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...it-people
 
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognicianit-people
 
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...it-people
 

More from it-people (20)

«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co
«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co
«Про аналитику и серебряные пули» Александр Подсобляев, Rambler&Co
 
«Scrapy internals» Александр Сибиряков, Scrapinghub
«Scrapy internals» Александр Сибиряков, Scrapinghub«Scrapy internals» Александр Сибиряков, Scrapinghub
«Scrapy internals» Александр Сибиряков, Scrapinghub
 
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains
«Отладка в Python 3.6: Быстрее, Выше, Сильнее» Елизавета Шашкова, JetBrains
 
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
 
«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс
«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс
«Ещё один Поиск Яндекса» Александр Кошелев, Яндекс
 
«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...
«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...
«How I Learned to Stop Worrying and Love the BFG: нагрузочное тестирование со...
 
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr
«Write once run anywhere — почём опиум для народа?» Игорь Новиков, Scalr
 
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
«Gensim — тематическое моделирование для людей» Иван Меньших, Лев Константино...
 
«Тотальный контроль производительности» Михаил Юматов, ЦИАН
«Тотальный контроль производительности» Михаил Юматов, ЦИАН«Тотальный контроль производительности» Михаил Юматов, ЦИАН
«Тотальный контроль производительности» Михаил Юматов, ЦИАН
 
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
«Детские болезни live-чата» Ольга Сентемова, Тинькофф Банк
 
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
«Микросервисы наносят ответный удар!» Олег Чуркин, Rambler&Co
 
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
«Память и Python. Что надо знать для счастья?» Алексей Кузьмин, ЦНС
 
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
«Что такое serverless-архитектура и как с ней жить?» Николай Марков, Aligned ...
 
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
«Python на острие бритвы: PyPy project» Александр Кошкин, Positive Technologies
 
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
«PyWat. А хорошо ли вы знаете Python?» Александр Швец, Marilyn System
 
«(Без)опасный Python», Иван Цыганов, Positive Technologies
«(Без)опасный Python», Иван Цыганов, Positive Technologies«(Без)опасный Python», Иван Цыганов, Positive Technologies
«(Без)опасный Python», Иван Цыганов, Positive Technologies
 
«Python of Things», Кирилл Борисов, Яндекс
«Python of Things», Кирилл Борисов, Яндекс«Python of Things», Кирилл Борисов, Яндекс
«Python of Things», Кирилл Борисов, Яндекс
 
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
«Как сделать так, чтобы тесты на Swift не причиняли боль» Сычев Александр, Ra...
 
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
«Клиенту и серверу нужно поговорить» Прокопов Никита, Cognician
 
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
«Кошелек или деньги: сложный выбор между памятью и процессором» Алексеенко Иг...
 

Recently uploaded

Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 

Recently uploaded (20)

Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 

Погружение в полнотекстовый поиск, используя Python - Андрей Солдатенко, Wargaming.NET

  • 1. Dive into full text search with Python Andrii Soldatenko 18-19 September 2015 @a_soldatenko
  • 2. About me: • Lead QA Automation Engineer at • Backend Python Developer at • Speaker at PyCon Ukraine 2014 • Speaker at PyCon Belarus 2015 • @a_soldatenko
  • 5. Text Search grep  -­‐-­‐ignore-­‐case  -­‐-­‐recursive  foo  books/   grep  -­‐-­‐ignore-­‐case  -­‐-­‐recursive  -­‐-­‐file=words.txt  books/ Entry.objects.get(headline__icontains='foo')   words  =  []   with  open('words.txt',  'r')  as  f:          words  =  f.readlines()   Entry.objects.get(headline__icontains_in=words)
  • 8. Simple sentences 1. The quick brown fox jumped over the lazy dog 2. Quick brown foxes leap over lazy dogs in summer
  • 9. Inverted index Term            Doc_1    Doc_2   -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐   Quick      |              |    X   The          |      X      |   brown      |      X      |    X   dog          |      X      |   dogs        |              |    X   fox          |      X      |   foxes      |              |    X   in            |              |    X   jumped    |      X      |   lazy        |      X      |    X   leap        |              |    X   over        |      X      |    X   quick      |      X      |   summer    |              |    X   the          |      X      |   -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐
  • 10. Inverted index Term            Doc_1    Doc_2   -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐   brown      |      X      |    X   quick      |      X      |   -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐   Total      |      2      |    1
  • 11. Inverted index: normalization Term            Doc_1    Doc_2   -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐   brown      |      X      |    X   dog          |      X      |    X   fox          |      X      |    X   in            |              |    X   jump        |      X      |    X   lazy        |      X      |    X   over        |      X      |    X   quick      |      X      |    X   summer    |              |    X   the          |      X      |    X   -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐ Term            Doc_1    Doc_2   -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐   Quick      |              |    X   The          |      X      |   brown      |      X      |    X   dog          |      X      |   dogs        |              |    X   fox          |      X      |   foxes      |              |    X   in            |              |    X   jumped    |      X      |   lazy        |      X      |    X   leap        |              |    X   over        |      X      |    X   quick      |      X      |   summer    |              |    X   the          |      X      |   -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐
  • 14. PostgreSQL:
 operators for textual data types -­‐-­‐-­‐  PostgreSQL  has  operators  for  textual  data  types:   -­‐-­‐-­‐  LIKE  -­‐  match  case-­‐sensitive   -­‐-­‐-­‐  ILIKE  -­‐  match  case-­‐insensitive   -­‐-­‐-­‐  ~  -­‐  Matches  POSIX  regular  expression,  case-­‐sensitive   -­‐-­‐-­‐  ~*  -­‐  Matches  POSIX  regular  expression,  case-­‐insensitive   select  'foo'  LIKE  'foo';                  -­‐-­‐  true   select  'bar'  ILIKE  'BAR';                -­‐-­‐  true     select  'abc'  LIKE  'b';                      -­‐-­‐  true   select  'abc'  LIKE  'c';                      -­‐-­‐  false   select  'abc'  ~  'abc';                        -­‐-­‐  true   select  'abc'  ~  '^a';                          -­‐-­‐  true   select  'abc'  ~  '(b|d)';                    -­‐-­‐  true   select  'abc'  ~  '^(b|c)';                  -­‐-­‐  false   select  'andrii'  ~*  '.*Andrii.*';  -­‐-­‐  true
  • 15. PostgreSQL:
 accuracy issue select  'prone'  like  '%one%';  -­‐-­‐true     select  'money'  like  '%one%';  -­‐-­‐true     select  'lonely'  like  '%one%';  -­‐-­‐true    
  • 16. Full text search in PostgreSQL 1.Creating tokens 2.Creating Lexems (Normaliztion) 3.storing preprocessed documents 4.Relevance ranking
  • 17. Full text search in PostgreSQL 27 built-in configurations for 10 languages Support of user-defined FTS configurations Pluggable dictionaries, parsers Inverted indexes
  • 18. functions to convert normal text to tsvector explain  SELECT  'a  fat  cat  sat  on  a  mat  and  ate  a  fat  rat'::tsvector  @@                  'cat  &  rat’::tsquery;                                  QUERY  PLAN                                   -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐    Result    (cost=0.00..0.01  rows=1  width=0)   (1  row)   explain  SELECT  'fat  &  cow'::tsquery  @@                    'a  fat  cat  sat  on  a  mat  and  ate  a  fat  rat'::tsvector;  -­‐-­‐  false                                  QUERY  PLAN                                   -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐    Result    (cost=0.00..0.01  rows=1  width=0)   (1  row)
  • 19. PostgreSQL:
 index management CREATE  FUNCTION  notes_vector_update()  RETURNS  TRIGGER  AS  $$   BEGIN          IF  TG_OP  =  'INSERT'  THEN                  new.search_index  =  to_tsvector('pg_catalog.english',  COALESCE(NEW.name,  ''));          END  IF;          IF  TG_OP  =  'UPDATE'  THEN                  IF  NEW.name  <>  OLD.name  THEN                          new.search_index  =  to_tsvector('pg_catalog.english',  COALESCE(NEW.name,  ''));                  END  IF;          END  IF;          RETURN  NEW;   END   $$  LANGUAGE  'plpgsql';  
  • 20. PostgreSQL:
 stopwords SELECT  to_tsvector('english','in  the  list  of  stop  words');                to_tsvector   -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐    'list':3  'stop':5  'word':6 /usr/pgsql-9.3/share/tsearch_data/english.stop
  • 22. PostgreSQL full-text search integration with django orm https://github.com/linuxlewis/djorm-ext-pgfulltext from  djorm_pgfulltext.models  import  SearchManager   from  djorm_pgfulltext.fields  import  VectorField   from  django.db  import  models   class  Page(models.Model):          name  =  models.CharField(max_length=200)          description  =  models.TextField()          search_index  =  VectorField()          objects  =  SearchManager(                  fields  =  ('name',  'description'),                  config  =  'pg_catalog.english',  #  this  is  default                  search_field  =  'search_index',  #  this  is  default                  auto_update_search_field  =  True          )
  • 23. For search just use search method of the manager https://github.com/linuxlewis/djorm-ext-pgfulltext >>>  Page.objects.search("documentation  &  about")   [<Page:  Page:  Home  page>]   >>>  Page.objects.search("about  |  documentation  |  django  |  home",  raw=True)   [<Page:  Page:  Home  page>,  <Page:  Page:  About>,  <Page:  Page:  Navigation>]
  • 24. Second way class  Page(models.Model):          name  =  models.CharField(max_length=200)          description  =  models.TextField()          objects  =  SearchManager(fields=None,  search_field=None)   >>>  Page.objects.search("documentation  &  about",  fields=('name',   'description'))   [<Page:  Page:  Home  page>]   >>>  Page.objects.search("about  |  documentation  |  django  |  home",   raw=True,  fields=('name',  'description'))   [<Page:  Page:  Home  page>,  <Page:  Page:  About>,  <Page:  Page:   Navigation>]
  • 25. Pros and Cons Pros: • Quick implementation • No dependency Cons: • Need manually manage indexes • Not as flexible as pure search engines • Not so fast as ElasticSearch • tied to PostgreSQL • no analytics data • no DSL only `&` and `|` queries • difficult to manage stop words
  • 28. ElasticSearch: Quick Intro Relational DB Databases TablesRows Columns ElasticSearch Indices FieldsTypes Documents
  • 30. ElasticSearch: Setup #!/bin/bash   VERSION=1.7.1   curl  -­‐L  -­‐O  https://download.elastic.co/elasticsearch/elasticsearch/ elasticsearch-­‐$VERSION.zip   unzip  elasticsearch-­‐$VERSION.zip   cd  elasticsearch-­‐$VERSION   #  Download  plugin  marvel   ./bin/plugin  -­‐i  elasticsearch/marvel/latest   echo  'marvel.agent.enabled:  false'  >>  ./config/elasticsearch.yml   #  run  elastic   ./bin/elasticsearch  -­‐d
  • 31. ElasticSearch: Setup $  curl  ‘http://localhost:9200/?pretty'   {      "status"  :  200,      "name"  :  "Dredmund  Druid",      "cluster_name"  :  "elasticsearch",      "version"  :  {          "number"  :  "1.7.1",          "build_hash"  :  "b88f43fc40b0bcd7f173a1f9ee2e97816de80b19",          "build_timestamp"  :  "2015-­‐07-­‐29T09:54:16Z",          "build_snapshot"  :  false,          "lucene_version"  :  "4.10.4"      },      "tagline"  :  "You  Know,  for  Search"   }
  • 33. Adding search functionality to Simple Model $  cat  myapp/models.py   from  django.db  import  models   from  django.contrib.auth.models  import  User   class  Page(models.Model):          user  =  models.ForeignKey(User)          name  =  models.CharField(max_length=200)          description  =  models.TextField()          def  __unicode__(self):                  return  self.name  
  • 34. Haystack: Installation $  pip  install  django-­‐haystack   $  cat  settings.py   INSTALLED_APPS  =  [          'django.contrib.admin',          'django.contrib.auth',          'django.contrib.contenttypes',          'django.contrib.sessions',          'django.contrib.sites',          #  Added.          'haystack',          #  Then  your  usual  apps...          'blog',   ]
  • 35. Haystack: Installation $  pip  install  elasticsearch   $  cat  settings.py   ...   HAYSTACK_CONNECTIONS  =  {          'default':  {                  'ENGINE':   'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',                  'URL':  'http://127.0.0.1:9200/',                  'INDEX_NAME':  'haystack',          },   }   ...
  • 36. Haystack: Creating SearchIndexes $  cat  myapp/search_indexes.py   import  datetime   from  haystack  import  indexes   from  myapp.models  import  Note   class  PageIndex(indexes.SearchIndex,  indexes.Indexable):          text  =  indexes.CharField(document=True,  use_template=True)          author  =  indexes.CharField(model_attr='user')          pub_date  =  indexes.DateTimeField(model_attr='pub_date')          def  get_model(self):                  return  Note          def  index_queryset(self,  using=None):                  """Used  when  the  entire  index  for  model  is  updated."""                  return  self.get_model().objects.                                            filter(pub_date__lte=datetime.datetime.now())
  • 37. Haystack: SearchQuerySet API from  haystack.query  import  SearchQuerySet   from  haystack.inputs  import  Raw   all_results  =  SearchQuerySet().all()   hello_results  =  SearchQuerySet().filter(content='hello')   unfriendly_results  =  SearchQuerySet().                                            exclude(content=‘hello’).                                            filter(content=‘world’)   #  To  send  unescaped  data:   sqs  =  SearchQuerySet().filter(title=Raw(trusted_query))  
  • 38. Keeping data in sync #  Update  everything.   ./manage.py  update_index  -­‐-­‐settings=settings.prod   #  Update  everything  with  lots  of  information  about  what's  going  on.   ./manage.py  update_index  -­‐-­‐settings=settings.prod  -­‐-­‐verbosity=2   #  Update  everything,  cleaning  up  after  deleted  models.   ./manage.py  update_index  -­‐-­‐remove  -­‐-­‐settings=settings.prod   #  Update  everything  changed  in  the  last  2  hours.   ./manage.py  update_index  -­‐-­‐age=2  -­‐-­‐settings=settings.prod   #  Update  everything  between  Dec.  1,  2011  &  Dec  31,  2011   ./manage.py  update_index  -­‐-­‐start='2011-­‐12-­‐01T00:00:00'  -­‐-­‐ end='2011-­‐12-­‐31T23:59:59'  -­‐-­‐settings=settings.prod
  • 39. Signals class  RealtimeSignalProcessor(BaseSignalProcessor):          """          Allows  for  observing  when  saves/deletes  fire  &  automatically  updates  the          search  engine  appropriately.          """          def  setup(self):                  #  Naive  (listen  to  all  model  saves).                  models.signals.post_save.connect(self.handle_save)                  models.signals.post_delete.connect(self.handle_delete)                  #  Efficient  would  be  going  through  all  backends  &  collecting  all  models                  #  being  used,  then  hooking  up  signals  only  for  those.          def  teardown(self):                  #  Naive  (listen  to  all  model  saves).                  models.signals.post_save.disconnect(self.handle_save)                  models.signals.post_delete.disconnect(self.handle_delete)                  #  Efficient  would  be  going  through  all  backends  &  collecting  all  models                  #  being  used,  then  disconnecting  signals  only  for  those.
  • 40. Haystack: Pros and Cons Pros: • easy to setup • looks like Django ORM but for searches • search engine independent • support 4 engines (Elastic, Solr, Xapian, Whoosh) Cons: • poor SearchQuerySet API • difficult to manage stop words • loose performance, because extra layer • Model - based
  • 41. Future FTS and Roadmap Django 1.9 • PostgreSQL Full Text Search (Marc Tamlyn) https://github.com/django/django/pull/4726 • Custom indexes (Marc Tamlyn) • etc.