o
    h\                     @   s  d dl Z d dlZd dlmZ d dlmZmZmZmZ d dl	m
Z
mZ d dlmZmZ d dlmZ d dlmZ d dlmZmZmZ d d	lmZ d d
lmZ d dlmZ d dlmZ d dlm Z  d dl!m"Z" d dl#m$Z$m%Z%m&Z&m'Z' d dl(m)Z)m*Z*m+Z+ d dl,m-Z-m.Z.m/Z/m0Z0 d dl1m2Z2 d dl3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z: d dl;m<Z<m=Z=m>Z>m?Z? G dd dZ@G dd dZAG dd de%ZBG dd deBZCG dd de&ZDG dd  d ZEG d!d" d"eEZFG d#d$ d$e$ZGeGZHdS )%    N)OrderedDict)NotSupportedErrorconnectionsroutertransaction)CaseWhen)AvgCount)
LOOKUP_SEPF)BooleanField
FloatField	TextField)Cast)Length)ManagerQ)	force_str)cached_property)BaseSearchBackendBaseSearchQueryCompilerBaseSearchResultsFilterFieldError)LexemeMatchExpressionSearchQuery)AutocompleteFieldRelatedFieldsSearchFieldget_indexed_models)
IndexEntry)AndBoostMatchAllNotOrPhrase	PlainText)ORbalanced_reduceget_content_type_pk!get_descendants_content_types_pksc                   @   sb   e Zd ZdZdd Zdd Zdd Zedd	 Zed
d Z	edd Z
edd ZdddZdS )ObjectIndexerzW
    Responsible for extracting data from an object to be inserted into the index.
    c                 C   s   || _ | | _|j| _d S N)objget_search_fieldssearch_fieldsconfig)selfr1   backend r7   l/var/www/html/ndineBlogger/venv/lib/python3.10/site-packages/wagtail/search/backends/database/mysql/mysql.py__init__7   s   
zObjectIndexer.__init__c                    s^   t |tr|S t |trd fdd|D S t |tr+d fdd| D S t|S )Nz, c                 3       | ]}  |V  qd S r0   prepare_value.0itemr5   r7   r8   	<genexpr>A       z.ObjectIndexer.prepare_value.<locals>.<genexpr>c                 3   r:   r0   r;   r=   r@   r7   r8   rA   D   rB   )
isinstancestrlistjoindictvaluesr   )r5   valuer7   r@   r8   r<   <   s   


zObjectIndexer.prepare_valuec                 c   s    t |tr|| ||fV  d S t |tr%|| ||fV  d S t |tr]||}|d u r5d S t |tr?| }n
t|rF| }|g}|D ]}|j	D ]}| 
||E d H  qPqKd S d S r0   )rC   r!   r<   	get_valuer   r    r   allcallablefieldsprepare_field)r5   r1   fieldsub_objsub_objs	sub_fieldr7   r7   r8   rN   H   s(   






zObjectIndexer.prepare_fieldc                 C   s   t | jjS )zO
        Returns the value to use as the ID of the record in the index
        )r   r1   pkr@   r7   r7   r8   ida   s   zObjectIndexer.idc                 C   sP   g }| j D ]}| | j|D ]\}}t|tr!|jdkr!|| qqd|S )z
        Returns all values to index as "title". This is the value of all SearchFields that have the field_name 'title'
        title r3   rN   r1   rC   r!   
field_nameappendrF   r5   textsrO   current_fieldrI   r7   r7   r8   rU   h      



zObjectIndexer.titlec                 C   sP   g }| j D ]}| | j|D ]\}}t|tr!|jdks!|| qqd|S )zr
        Returns all values to index as "body". This is the value of all SearchFields excluding the title
        rU   rV   rW   rZ   r7   r7   r8   bodyx   r]   zObjectIndexer.bodyc                 C   sF   g }| j D ]}| | j|D ]\}}t|tr|| qqd|S )zl
        Returns all values to index as "autocomplete". This is the value of all AutocompleteFields
        rV   )r3   rN   r1   rC   r   rY   rF   rZ   r7   r7   r8   autocomplete   s   



zObjectIndexer.autocompleteFc                 C   s&   dd |D }dd |D }d |S )zW
        Converts an array of strings into a SearchVector that can be indexed.
        c                 S   s   g | ]
\}}|  |fqS r7   )stripr>   textweightr7   r7   r8   
<listcomp>       z+ObjectIndexer.as_vector.<locals>.<listcomp>c                 S   s   g | ]
\}}|r||fqS r7   r7   ra   r7   r7   r8   rd      re   rV   )rF   )r5   r[   for_autocompleter7   r7   r8   	as_vector   s   
zObjectIndexer.as_vectorNF)__name__
__module____qualname____doc__r9   r<   rN   r   rT   rU   r^   r_   rg   r7   r7   r7   r8   r/   2   s    



r/   c                   @   sf   e Zd Zdd Zdd Zdd Zddd	Zd
d Zdd Zdd Z	dd Z
dd Zdd Zdd ZdS )Indexc                 C   s`   || _ | j j| _ttt | _ttt | _	| jj
dks$| j	j
dkr(tdtj | _d S )Nmysqlz5You must select a MySQL database to use MySQL search.)r6   
index_namenamer   r   db_for_readr#   read_connectiondb_for_writewrite_connectionvendorr   _default_managerrK   entriesr5   r6   r7   r7   r8   r9      s   
zIndex.__init__c                 C      d S r0   r7   r5   modelr7   r7   r8   	add_model      zIndex.add_modelc                 C   ry   r0   r7   r@   r7   r7   r8   refresh   r}   zIndex.refreshFc                 C   sn   | j jtddjddtdd }|r| j }n| j jdd}|jtddjddj|td d d	S )
a  
        Refreshes the value of the title_norm field.

        This needs to be set to 'lavg/ld' where:
         - lavg is the average length of titles in all documents (also in terms)
         - ld is the length of the title field in this document (in terms)
        rU   )title_lengthr   )title_length__gtr   title_length__avg      ?)
title_normN)rw   annotater   filter	aggregater	   updater   )r5   fulllavgrw   r7   r7   r8   _refresh_title_norms   s   

zIndex._refresh_title_normsc                 C   sF   |j jtdt dd}t|}| jj|dj|d}|	  d S )NrS   	object_idr   content_type_id__inobject_id__in)
rv   r   r   r   rH   r.   rw   r   excludedelete)r5   r{   existing_pkscontent_types_pksstale_entriesr7   r7   r8   delete_stale_model_entries   s   
z Index.delete_stale_model_entriesc                 C   s"   t  D ]}|jjs| | qd S r0   )r"   _metaparentsr   rz   r7   r7   r8   delete_stale_entries   s
   

zIndex.delete_stale_entriesc                 C   s   |  |jj|g d S r0   )	add_itemsr   r{   r5   r1   r7   r7   r8   add_item   s   zIndex.add_itemc              
   C   s   i }|D ]}|j |j|jf||j< q| jj|d}t|j| djddd}|D ]}|| \}}	}
|j|dj	||	|
d q*g }| D ]}||vr_|| \}}	}
|
t||||	|
d qF| j| |   d S )	N)content_type_idr   r   T)flatr   )rU   r_   r^   )r   r   rU   r_   r^   )rU   r_   r^   rT   rw   r   	frozensetkeysvalues_listr   rY   r#   bulk_creater   )r5   content_type_pkindexersids_and_dataindexerindex_entries_for_ctindexed_ids
indexed_idrU   r_   r^   to_be_createdr   r7   r7   r8   add_items_update_then_create   sB   
z"Index.add_items_update_then_createc                    sF   |  }|sd S  fdd|D }|r!t|} j}||| d S d S )Nc                    s   g | ]}t | jqS r7   )r/   r6   )r>   r1   r@   r7   r8   rd     s    z#Index.add_items.<locals>.<listcomp>)r2   r-   r   )r5   r{   objsr3   r   r   update_methodr7   r@   r8   r     s   zIndex.add_itemsc                 C   s   |j  j| jjd d S )Nusing)index_entriesrK   _raw_deletert   alias)r5   r?   r7   r7   r8   delete_item  s   zIndex.delete_itemc                 C   s   | j S r0   )rp   r@   r7   r7   r8   __str__"     zIndex.__str__Nrh   )ri   rj   rk   r9   r|   r~   r   r   r   r   r   r   r   r   r7   r7   r7   r8   rm      s    

'rm   c                       s   e Zd ZdZdZeZddgZ fddZdd Z	d	d
 Z
d"ddZd#ddZdd Zdd Zdd Zdd Zdd Zd"ddZdd Zdd Zd d! Z  ZS )$MySQLSearchQueryCompilerandFrU   r^   c                    sJ   t  j|i |   jd u r _d S  fddjD _d S )Nc                    s   i | ]
}|j | d qS ))rM   )get_search_field)r>   field_lookuplocal_search_fieldsr5   r7   r8   
<dictcomp>7  s    z5MySQLSearchQueryCompiler.__init__.<locals>.<dictcomp>)superr9   get_search_fields_for_modelrM   r3   )r5   argskwargs	__class__r   r8   r9   ,  s   

z!MySQLSearchQueryCompiler.__init__c                 C      |j S r0   r4   rx   r7   r7   r8   
get_config>  r   z#MySQLSearchQueryCompiler.get_configc                 C      | j j S r0   )querysetr{   get_searchable_search_fieldsr@   r7   r7   r8   r   A     z4MySQLSearchQueryCompiler.get_search_fields_for_modelNc                 C   s~   |d u r| j }t|v r|td\}}nd }|D ]$}t|| jr)|j|kr)|  S t|tr<|j|kr<| ||j  S qd S )N   )	r3   r   splitrC   TARGET_SEARCH_FIELD_TYPErX   r    r   rM   )r5   r   rM   sub_field_namerO   r7   r7   r8   r   D  s   

z)MySQLSearchQueryCompiler.get_search_fieldc                    sF  t |tr@dd td|jD }|stdS | }t| jd}|D ]}t| d}|j	dkr7||M }q%||O }q%t|S t |t
rLt|jdd	S t |trad
}t|t j|j dS t |troj|j  dS t |ttfr fdd|jD }	t |t}
 r|
 }
|
rtdd |	S tdd |	S td|jj )Nc                 S   s   g | ]}|r|qS r7   r7   )r>   termr7   r7   r8   rd   ^      zGMySQLSearchQueryCompiler.build_search_query_content.<locals>.<listcomp>z\W+ )invertprefixr   r   phrase)search_typez=The Boost query is not supported by the MySQL search backend.c                    s   g | ]	}j | d qS )r   build_search_query_content)r>   subqueryr   r5   r7   r8   rd     s    c                 S   s   | |@ S r0   r7   abr7   r7   r8   <lambda>      zEMySQLSearchQueryCompiler.build_search_query_content.<locals>.<lambda>c                 S   s   | |B S r0   r7   r   r7   r7   r8   r     r   z2`%s` is not supported by the MySQL search backend.)rC   r*   rer   query_stringr   popr   LAST_TERM_IS_PREFIXoperatorr)   r%   warningswarnRuntimeWarningr   r   r'   r$   r(   
subqueriesr,   NotImplementedErrorr   ri   )r5   queryr   terms	last_termlexemesr   
new_lexememsgsubquery_lexemesis_andr7   r   r8   r   Z  sF   







z3MySQLSearchQueryCompiler.build_search_query_contentc                 C   s
   |  |S r0   r   )r5   r   r7   r7   r8   build_search_query     
z+MySQLSearchQueryCompiler.build_search_queryc                 C   s   t dt dft ddfgS )Nindex_entries__titleindex_entries__title_normindex_entries__bodyr   r   r5   search_queryr7   r7   r8   get_index_vectors  s   
z*MySQLSearchQueryCompiler.get_index_vectorsc                 C      t  r0   r   r   r7   r7   r8   get_fields_vectors  r   z+MySQLSearchQueryCompiler.get_fields_vectorsc                 C   s   | j d u r
| |S | |S r0   )rM   r   r   r   r7   r7   r8   get_search_vectors  s   


z+MySQLSearchQueryCompiler.get_search_vectorsc                    s:    fdd|D }|d }|dd  D ]}||7 }q|S )Nc                    s&   g | ]\}}j |j d | qS )r   )build_tsrankr   )r>   vectorboostr4   r5   r7   r8   rd     s    zCMySQLSearchQueryCompiler._build_rank_expression.<locals>.<listcomp>r   r   r7   )r5   vectorsr4   rank_expressionsrank_expressionother_rank_expressionr7   r   r8   _build_rank_expression  s   
z/MySQLSearchQueryCompiler._build_rank_expressionc                 C   s6  t | jtr| j|| S t | jtrt | jjtr| j S t | jtr,| jj}d}n| j}d}| |}t|| j	t
 d}tt|dddd}t|dgt dtd t|dgt d }	tjj|	d	jt| jjd
}
|s|
|}
| jr|
|	 }
n|
|}
|
|| }
dd |
D }| jj|d}|S )NTF)columnsoutput_field)then)defaultrU   r   r^   )scorer   c                 S   s   h | ]}|j qS r7   r   )r>   index_entryr7   r7   r8   	<setcomp>  s    z2MySQLSearchQueryCompiler.search.<locals>.<setcomp>)id__in)rC   r   r&   r   r'   r   noner   r   FTS_TABLE_FIELDSr   r   r   r   r   r#   objectsr   r   r.   r{   order_by_relevanceorder_bydescr   )r5   r4   startstopscore_fieldr   negatedr   match_expressionscore_expressionr   
object_idsresultsr7   r7   r8   search  sP   







zMySQLSearchQueryCompiler.searchc                 C   s(   | | jjd | }tdi ||iS )N__r7   )get_attnamer   r{   r   )r5   rO   lookuprI   lhsr7   r7   r8   _process_lookup	  s   z(MySQLSearchQueryCompiler._process_lookupc                 C   s
   t g dS )N)pk__inr   r@   r7   r7   r8   _process_match_none  r   z,MySQLSearchQueryCompiler._process_match_nonec                 C   s@   |dkr	t | }n|dkrtdd |D }nd S |r| }|S )NANDr+   c                 S   s   g | ]}t |qS r7   r   )r>   filr7   r7   r8   rd     r   z=MySQLSearchQueryCompiler._connect_filters.<locals>.<listcomp>)r   r+   )r5   filters	connectorr  qr7   r7   r8   _connect_filters  s   
z)MySQLSearchQueryCompiler._connect_filtersr0   rh   )ri   rj   rk   DEFAULT_OPERATORr   r!   r   r  r9   r   r   r   r   r   r   r   r   r  r  r!  r#  r)  __classcell__r7   r7   r   r8   r   &  s&    

G
Ir   c                   @   s:   e Zd ZdZeZdgZdd Zdd Zdd Z	d	d
 Z
dS )MySQLAutocompleteQueryCompilerTr_   c                 C   r   r0   )autocomplete_configrx   r7   r7   r8   r   %  r   z)MySQLAutocompleteQueryCompiler.get_configc                 C   r   r0   )r   r{   get_autocomplete_search_fieldsr@   r7   r7   r8   r   (  r   z:MySQLAutocompleteQueryCompiler.get_search_fields_for_modelc                 C   s   t ddfgS )Nindex_entries__autocompleter   r   r   r7   r7   r8   r   +     z0MySQLAutocompleteQueryCompiler.get_index_vectorsc                 C   r   r0   r   r   r7   r7   r8   r   .  r   z1MySQLAutocompleteQueryCompiler.get_fields_vectorsN)ri   rj   rk   r   r   r   r  r   r   r   r   r7   r7   r7   r8   r,     s    r,  c                   @   s2   e Zd ZdddZdd Zdd ZdZd	d
 ZdS )MySQLSearchResultsFc                 C   s:   |rd }d }n| j }| j}| jj| j| j||| jdS )N)r  )r  r  query_compilerr  r   r6   _score_field)r5   	for_countr  r  r7   r7   r8   get_queryset3  s   zMySQLSearchResults.get_querysetc                 C   s   t |  S r0   )rE   r5  r@   r7   r7   r8   
_do_searchB  r   zMySQLSearchResults._do_searchc                 C   s   | j dd S )NT)r4  )r5  countr@   r7   r7   r8   	_do_countE  s   zMySQLSearchResults._do_countTc                    s   | j  }|d u r td  d   d | j jjj d  d| j | j | jd d }|	 j
tddd}t fd	d
|D S )Nz(Cannot facet search results with field "z!". Please add index.FilterField('z') to z.search_fields.rX   rS   r7  z-countc                    s   g | ]
}|  |d  fqS r:  r7   )r>   resultr9  r7   r8   rd   a  re   z,MySQLSearchResults.facet.<locals>.<listcomp>)r2  _get_filterable_fieldr   r   r{   ri   r  r   r6   rH   r   r
   r  r   )r5   rX   rO   r   r  r7   r9  r8   facetJ  s4   
zMySQLSearchResults.facetNrh   )ri   rj   rk   r5  r6  r8  supports_facetr=  r7   r7   r7   r8   r1  2  s    
r1  c                   @   s$   e Zd Zdd Zdd Zdd ZdS )MySQLSearchRebuilderc                 C   s
   || _ d S r0   )indexr5   r@  r7   r7   r8   r9   f  r   zMySQLSearchRebuilder.__init__c                 C   s   | j   | j S r0   )r@  r   r@   r7   r7   r8   r  i  s   
zMySQLSearchRebuilder.startc                 C   s   | j jdd d S )NTr   )r@  r   r@   r7   r7   r8   finishm  s   zMySQLSearchRebuilder.finishN)ri   rj   rk   r9   r  rC  r7   r7   r7   r8   r?  e  s    r?  c                       s8   e Zd Z fddZ fddZdd Zdd Z  ZS )	MySQLSearchAtomicRebuilderc                    s(   t  | tj|jjd| _d| _d S )Nr   F)r   r9   r   atomicrt   r   transaction_openedrA  r   r7   r8   r9   r  s   
z#MySQLSearchAtomicRebuilder.__init__c                    s   | j   d| _t  S NT)r   	__enter__rF  r   r  r@   r   r7   r8   r  w  s   

z MySQLSearchAtomicRebuilder.startc                 C   s(   | j jdd | jd d d  d| _d S )NTrB  F)r@  r   r   __exit__rF  r@   r7   r7   r8   rC  |  s   
z!MySQLSearchAtomicRebuilder.finishc                 C   s   | j rd| j_|   d S d S rG  )rF  r   needs_rollbackrC  r@   r7   r7   r8   __del__  s   z"MySQLSearchAtomicRebuilder.__del__)ri   rj   rk   r9   r  rC  rK  r+  r7   r7   r   r8   rD  q  s
    rD  c                       sp   e Zd ZeZeZeZe	Z
eZ fddZdd Zdd Zdd Zd	d
 Zdd Zdd Zdd Zdd Z  ZS )MySQLSearchBackendc                    sB   t  | |dd| _d | _d | _|ddr| j| _d S d S )NINDEXr	  ATOMIC_REBUILDF)r   r9   getro   r4   r-  atomic_rebuilder_classrebuilder_class)r5   paramsr   r7   r8   r9     s   zMySQLSearchBackend.__init__c                 C   s   t | S r0   )rm   rz   r7   r7   r8   get_index_for_model  s   z&MySQLSearchBackend.get_index_for_modelc                 C   s   |  |jjS r0   )rS  r   r{   r   r7   r7   r8   get_index_for_object  r0  z'MySQLSearchBackend.get_index_for_objectc                 C   s0   dd t  D D ]}tj j|jd q	d S )Nc                 S   s   g | ]	}|j d kr|qS )rn   )ru   )r>   
connectionr7   r7   r8   rd     s
    
z2MySQLSearchBackend.reset_index.<locals>.<listcomp>r   )r   rK   r#   rv   r   r   )r5   rU  r7   r7   r8   reset_index  s
   
zMySQLSearchBackend.reset_indexc                 C   ry   r0   r7   rz   r7   r7   r8   add_type  r}   zMySQLSearchBackend.add_typec                 C   ry   r0   r7   r@   r7   r7   r8   refresh_index  r}   z MySQLSearchBackend.refresh_indexc                 C      |  || d S r0   )rT  r   r   r7   r7   r8   add     zMySQLSearchBackend.addc                 C   s"   |r|  |d || d S d S )Nr   )rT  r   )r5   r{   obj_listr7   r7   r8   add_bulk  s   zMySQLSearchBackend.add_bulkc                 C   rY  r0   )rT  r   r   r7   r7   r8   r     r[  zMySQLSearchBackend.delete)ri   rj   rk   r   query_compiler_classr,  !autocomplete_query_compiler_classr1  results_classr?  rQ  rD  rP  r9   rS  rT  rV  rW  rX  rZ  r]  r   r+  r7   r7   r   r8   rL    s    rL  )Ir   r   collectionsr   	django.dbr   r   r   r   django.db.modelsr   r   django.db.models.aggregatesr	   r
   django.db.models.constantsr   django.db.models.expressionsr   django.db.models.fieldsr   r   r   %django.db.models.functions.comparisonr   django.db.models.functions.textr   django.db.models.managerr   django.db.models.query_utilsr   django.utils.encodingr   django.utils.functionalr   wagtail.search.backends.baser   r   r   r   ,wagtail.search.backends.database.mysql.queryr   r   r   wagtail.search.indexr   r    r!   r"   wagtail.search.modelsr#   wagtail.search.queryr$   r%   r&   r'   r(   r)   r*   wagtail.search.utilsr+   r,   r-   r.   r/   rm   r   r,  r1  r?  rD  rL  SearchBackendr7   r7   r7   r8   <module>   s@    $m  {32