Exclude results from Elastic Search based on field content - symfony

I use FOQElasticaBundle to integrate Elastic Search into my Symfony2 project. I have an entity called Recipe, this entity has property $draft that indicates that the recipe is not complete yet. I want to exclude recipes that has the property $draft = 1 from Elastic Search results.
This is part of my foq_elastica configuration:
...
types:
chef:
mappings:
surname: {boost: 5}
name: {boost: 4}
nbLikes: { index: not_analyzed }
nbFollowers: { index: not_analyzed }
persistence:
driver: orm
model: Interacso\ApiBundle\Entity\Chef
identifier: id
provider: ~
finder: ~
listener: ~
recipe:
mappings:
name: {boost: 100}
chefName: {boost: 10}
chefSurname: {boost: 10}
bookNames: {boost: 5}
ingredientNames: {boost: 2}
tagNames: {boost: 2}
persistence:
driver: orm
model: Interacso\ApiBundle\Entity\Recipe
identifier: id
provider: ~
finder: ~
listener: ~
....
Any suggestion?

Ok, I found the answer by myself, if someone has the same problem, the response is to specify a query builder in the config file:
recipe:
mappings:
name: {boost: 100}
chefName: {boost: 10}
chefSurname: {boost: 10}
bookNames: {boost: 5}
ingredientNames: {boost: 2}
tagNames: {boost: 2}
persistence:
driver: orm
model: Interacso\ApiBundle\Entity\Recipe
identifier: id
provider:
query_builder_method: buildIfIsNotDraft
finder: ~
listener: ~
And implement the specified method in the repository returning a Doctrine Query Builder. More info in the official documentation of the bundle: https://github.com/Exercise/FOQElasticaBundle

Related

Unrecognized option "types" | FOS Elastica & Symfony

I am able to create indexes 1 by 1 but my purpose is to have 1 big index with subindexes to search. (I am reproducing an existing app but upgrading dependencies)
Symfony : 5.4*
FOS-Elastica : 6.1
Elastic : 7*
This is my error message and if I change types to properties I have similar errors. I have been trying to switch and indent differently all day:
Unrecognized option "types" under "fos_elastica.indexes.app". Available options are "_id", "_routing", "_source", "analyzer", "client", "date_detection", "dynamic", "dynamic_date_formats", "dynamic_templates", "finder", "index_
name", "index_prototype", "indexable_callback", "numeric_detection", "persistence", "properties", "serializer", "settings", "use_alias".
What am I doing wrong please ?
#app/config/config.yml
fos_elastica:
clients:
default: { host: localhost, port: 9200 }
indexes:
app:
settings:
analysis:
analyzer:
fr:
tokenizer: standard
filter: [ lowercase, stop_fr, snowball_fr ]
autocomplete:
type: custom
tokenizer: whitespace
filter: [ lowercase, engram, elision ]
csv:
type: pattern
pattern: '\s*,\s*'
lowercase: false
filter:
snowball_fr:
type: "snowball"
language: "French"
stop_fr:
type: "stop"
stopwords: "_french_"
engram:
type: edge_ngram
min_gram: 2
max_gram: 15
types:
# ---------
# USER
# ---------
user:
properties:
username: ~
email: ~
organization:
type: object
properties:
id: { index: true }
code: { index: true }
name:
index: true
type: text
fields:
source: { type: text, index: true }
persistence:
driver: orm # orm, mongodb, propel are available
model: App\Entity\User
provider: ~
listener: ~
finder: ~
So I was also figuring out how to deal with the same issue as yours, and I do confirm lot of the docs and blogposts out there use the config struture you posted. However when I went back to the v6.1 documentation of the bundle I found this:
Dynamic templates
Dynamic templates allow to define mapping templates
that will be applied when dynamic introduction of fields / objects
happens.
Documentation
fos_elastica:
indexes:
user:
dynamic_templates:
my_template_1:
match: apples_*
mapping:
type: float
my_template_2:
match: *
match_mapping_type: text
mapping:
type: keyword
properties:
username: { type: text }
So in your case a working config would look like:
#app/config/config.yml
fos_elastica:
clients:
default: { host: localhost, port: 9200 }
indexes:
user:
settings:
analysis:
analyzer:
fr:
tokenizer: standard
filter: [ lowercase, stop_fr, snowball_fr ]
autocomplete:
type: custom
tokenizer: whitespace
filter: [ lowercase, engram, elision ]
csv:
type: pattern
pattern: '\s*,\s*'
lowercase: false
filter:
snowball_fr:
type: "snowball"
language: "French"
stop_fr:
type: "stop"
stopwords: "_french_"
engram:
type: edge_ngram
min_gram: 2
max_gram: 15
properties:
username: ~
email: ~
organization:
type: object
properties:
id: { index: true }
code: { index: true }
name:
index: true
type: text
fields:
source: { type: text, index: true }
persistence:
driver: orm # orm, mongodb, propel are available
model: App\Entity\User
provider: ~
listener: ~
finder: ~

Error "No providers were registered for index "apple"" after FOSElasticaBundle Update

I am trying to update my Symfony version and i have troubles with FOS elastica-bundle 5.0.3.
I have updated my ES server to 5.6.
If i dump my old ES datas and put them into the new server everythings works fine.
But if i try to do an
fos:elastica:populate
i have this error :
No providers were registered for index "apple".
My old configuration (FOSEB 3.0) was not needing any providers for this index and i don't understand how to add one for my new configuration.
I have searched all day how to configure this index provider to make the populate work on my new environnment and i have tried lot of things but with no success.
My elastica.yml :
fos_elastica:
clients:
default: { host: "%elasticsearch.ip%", port: "%elasticsearch.port%" }
indexes:
apple:
client: default
settings:
index:
analysis:
analyzer:
custom_index_analyzer:
type: custom
tokenizer: standard
filter : [lowercase, asciifolding, nGram]
custom_search_analyzer:
type: custom
tokenizer: standard
filter : [lowercase, asciifolding]
filter:
nGram:
type: nGram
min_gram: 3
max_gram: 20
token_chars: ['letter', 'digit', 'punctuation', 'symbol']
types:
banana:
properties:
id: { boost: 5 }
persistence:
identifier: id
driver: orm
model: apple\AppBundle\Entity\banana\banana
provider:
service: "#apple_app.elastica.provider.banana"
orange:
properties:
id: { boost: 5 }
persistence:
identifier: id
driver: orm
model: apple\AppBundle\Entity\banana\orange
provider:
service: "#apple_app.elastica.provider.orange"
My services :
services:
# manager
apple_app.elastica.manager.abstract:
class: apple\AppBundle\Manager\Common\ElasticaManager
abstract: true
calls:
- ['setTranslator', ['#translator']]
- ['setDefaultLocale', ['%locale%']]
- ['setLocales', ['%available_languages%']]
apple_app.elastica.manager.banana:
class: apple\AppBundle\Manager\Elastica\bananaManager
parent: apple_app.elastica.manager.abstract
calls:
- ['setIndexes', [{'banana': '#fos_elastica.index.apple.banana'}]]
- ['setContainer', ['#service_container']]
apple_app.elastica.manager.orange:
class: apple\AppBundle\Manager\Elastica\orangeManager
parent: apple_app.elastica.manager.abstract
calls:
- ['setIndexes', [{'orange': '#fos_elastica.index.apple.orange'}]]
# provider
apple_app.elastica.provider.abstract:
class: apple\AppBundle\Provider\Common\AbstractProvider
abstract: true
calls:
- ['setEntityManager', ['#doctrine.orm.entity_manager']]
apple_app.elastica.provider.apple:
class: apple\AppBundle\Provider\Common\AbstractProvider
abstract: true
calls:
- ['setEntityManager', ['#doctrine.orm.entity_manager']]
apple_app.elastica.provider.banana:
parent: apple_app.elastica.provider.abstract
class: apple\AppBundle\Provider\bananaProvider
tags:
- { name: fos_elastica.provider, index: apple, type: banana }
calls:
- ['setIndex', ['#fos_elastica.index.apple.banana']]
- ['setElasticaManager', ['#apple_app.elastica.manager.banana']]
apple_app.elastica.provider.orange:
parent: apple_app.elastica.provider.abstract
class: apple\AppBundle\Provider\orangeProvider
tags:
- { name: fos_elastica.provider, index: apple, type: orange }
calls:
- ['setIndex', ['#fos_elastica.index.apple.orange']]
- ['setElasticaManager', ['#apple_app.elastica.manager.orange']]
# listener
apple_app.elastica.listener.abstract:
class: apple\AppBundle\Listener\Common\ElasticaListener
calls:
- ['setDefaultLocale', ['%locale%']]
- ['setLocales', ['%available_languages%']]
apple_app.elastica.listener.banana:
parent: apple_app.elastica.listener.abstract
class: apple\AppBundle\Listener\Elastica\bananaListener
calls:
- ['setManager', ['#apple_app.elastica.manager.banana']]
- ['setIndex']
tags:
- { name: doctrine.event_subscriber }
apple_app.elastica.listener.orange:
parent: apple_app.elastica.listener.abstract
class: apple\AppBundle\Listener\Elastica\orangeListener
calls:
- ['setManager', ['#apple_app.elastica.manager.orange']]
- ['setIndex']
tags:
- { name: doctrine.event_subscriber }
Any help or idea would be wonderful.
Thank you in advance

Index a foreign key label with FosElasticaBundle

When I index my relationnal database (Postgresql), I want to get the string value intead of the foreign key id (recreate the relation between the two tables personn and country..)
I wish to do that in the fos_elastica.yml mapping file
Example:
fos_elastica:
clients:
default: { host: %elastic_host%, port: %elastic_port% }
indexes:
ex_app:
client: default
types:
personn:
mappings:
id:
type: integer
name:
type: text
boost: 5
firstname:
type: text
boost: 3
dateofbirth:
type: date
country:
type: integer
persistence:
driver: orm
model: AppBundle\Entity\Personn
finder: ~
provider: ~
listener: ~
I want to find the person by typing the name of the country and not the country id.
I'm pretty sure that you should use "nested" :
fos_elastica:
clients:
default: { host: %elastic_host%, port: %elastic_port% }
indexes:
ex_app:
client: default
types:
personn:
mappings:
id:
type: integer
name:
type: text
boost: 5
firstname:
type: text
boost: 3
dateofbirth:
type: date
country:
type: "nested"
properties:
id:
type : integer
label:
type: text
persistence:
driver: orm
model: AppBundle\Entity\Personn
finder: ~
provider: ~
listener: ~

symfony elastic search match exact term not working

I use symfony with fos elastica bundle but i have some problems
I have an entity content with link with other entity categorie (with name and slugname) x content have only 1 category.
I have install the bundle and configure the yml files like this
fos_elastica:
clients:
default: { host: 127.0.0.1, port: 9200 }
serializer:
callback_class: FOS\ElasticaBundle\Serializer\Callback
serializer: serializer
indexes:
portail:
client: default
settings:
index:
analysis:
analyzer:
custom_analyzer :
type: custom
tokenizer: nGram
char_filter: [html_strip]
filter: [stopwords, lowercase, snowball, elision]
custom_analyzer_simple :
type: custom
tokenizer: whitespace
filter: [lowercase]
custom_search_analyzer :
type: custom
char_filter: [html_strip]
tokenizer: whitespace
filter: [stopwords, lowercase, snowball, elision]
custom_search_analyzer_simple :
type: custom
tokenizer: whitespace
filter: [lowercase]
tokenizer:
nGram:
type: nGram
min_gram: 4
max_gram: 20
filter:
snowball:
type: snowball
language: French
elision:
type: elision
articles: [l, m, t, qu, n, s, j, d]
stopwords:
type: stop
stopwords: [_french_]
ignore_case : true
worddelimiter :
type: word_delimiter
types:
Content:
mappings:
titre:
type: string
index_analyzer: custom_analyzer
search_analyzer : custom_search_analyzer
preview:
type: string
index_analyzer: custom_analyzer
search_analyzer : custom_search_analyzer
contenu:
type: string
index_analyzer: custom_analyzer
search_analyzer : custom_search_analyzer
categorie:
type: object
properties:
slugnom:
type: string
index: not_analyzed
search_analyzer : custom_search_analyzer_simple
persistence:
driver: orm
model: PO\EtablissementBundle\Entity\Content
provider: ~
listener:
logger: true
finder: ~
Page:
mappings:
titre:
type: string
index_analyzer: custom_analyzer
search_analyzer : custom_search_analyzer
persistence:
driver: orm
model: PO\EtablissementBundle\Entity\PageEtablissement
provider: ~
listener:
logger: true
finder: ~
Etablissement:
mappings:
nom:
type: string
index_analyzer: custom_analyzer
search_analyzer : custom_search_analyzer
contents:
type: object
categories:
type: nested
properties:
slugnom:
type: string
index: not_analyzed
search_analyzer : custom_search_analyzer_simple
sous_categories:
type: nested
properties:
slugnom:
type: string
index: not_analyzed
persistence:
driver: orm
model: PO\EtablissementBundle\Entity\Etablissement
provider: ~
listener:
logger: true
finder: ~
I want to have some flexibility but on the content categorie slugname i want to search exactly the word for example arts-de-la-rue but when i make a search i found result with categorie = arts or categorie = lecture, i don't understand the problem :(
If somebody can help me :)
You have to setup your mapping for that field
your field: { type: "string", index: "not_analyzed" }
And just to be sure destroy the type and populate it again.
You need to setup an keyword based analyzer for that.
The ngram on your analyzer will destroy any slug.
It is possible to setup multiple different analyzers per field, but I dont know if it is supported by the FOS\ElasticaBundle: https://www.elastic.co/guide/en/elasticsearch/reference/current/multi-fields.html
Later you can do a "filtered" query (term filter) against this new raw field.
Thanks for your help i have done some mistake in my configuration. I have put a type nested and in fact it's objet and the name of the properties are not good.
Now it's working perfectly :)

Auto index child objects in fos elastica

I have created an elastic search mapping in config.yml which is using doctrine orm, the issue is that when I create a new document the index is auto populated for the top most object which is "documents" but not for any child objects such as "Folder, Authors, Comments ...", can someone suggest if I am missing any flag or any settings. Below is my Elastica configuration:
# Elastica Configuration
fos_elastica:
clients:
default: { host: localhost, port: 9200 }
indexes:
website:
client: default
index_name: docova
types:
documents:
mappings:
Doc_Title: ~
Description: ~
Date_Created: ~
Doc_Status: ~
Keywords: ~
folder:
type: "object"
properties:
id: ~
Library:
type: "object"
properties:
id: ~
Author:
type: "object"
properties:
username: ~
Comments:
type: "object"
properties:
comment: ~
Form_Values:
type: "object"
properties:
Field_Value: ~
Bookmarks:
type: "object"
properties:
Target_Folder:
type: "object"
properties:
id: ~
DocType:
type: "object"
properties:
id: ~
Doc_Name: ~
Attachments:
type: "object"
properties:
File_Name:
content:
type: attachment
persistence:
driver: orm
model: Docova\DocovaBundle\Entity\Documents
provider: ~
listener: ~
finder: ~
Thnx.
i've found a solution here.
Symfony2 FOSElasticaBundle update index for all entities related to the entity updated
Note : In my version of FOSElastica, Listener is not in the ORM folder but in FOS\ElasticaBundle\Doctrine and the argument has changed from LifecycleEventArgs $eventArgs to \Doctrine\Common\EventArgs $eventArgs.
EDIT : For this case, you have to override postPersist too.
public function postPersist(\Doctrine\Common\EventArgs $eventArgs)
{
$entity = $eventArgs->getEntity();
if ($entity instanceof $this->objectClass && $this->isObjectIndexable($entity)) {
$this->scheduledForInsertion[] = $entity;
$this->inicializaPost();
$this->objectPersisterPost->replaceOne($entity->getPost());
}
}

Resources