diff --git a/front/src/components/OrganizationAutoCompleter.vue b/front/src/components/OrganizationAutoCompleter.vue index 25b261cdb095661c0e2f62b51a802ae8388d67a2..ce7c3fb837b0697980e884370cefe8f2997dd781 100644 --- a/front/src/components/OrganizationAutoCompleter.vue +++ b/front/src/components/OrganizationAutoCompleter.vue @@ -1,43 +1,47 @@ <template> - <v-select @search="handlerSearchOrganisation" - placeholder="Rechercher une structure" - :options="filteredOptions" - label="label" - v-model="value" - :reduce="item => item.id" - @input="setSelected" - > - <template #list-header> - <li style="text-align: center"> - <label for="display_closed"> - Afficher les structures fermées - <input type="checkbox" v-model="displayClosed" id="display_closed" /> - </label> - </li> - </template> - - <template #option="{ id,code, shortname, longname, city, country, label, closed, email, phone }" - class="result-item"> - <div class="result-item" :class="{'organization-closed': closed }"> - <h4 style="margin: 0"> - <code v-if="code">{{ code }}</code> - <span> - <strong v-if="shortname">{{ shortname }}</strong> - <em v-if="longname">{{ longname }}</em> - </span> - </h4> - <div v-if="email || phone" class="infos"> - <span v-if="email"><i class="icon-mail"></i> {{ email }}</span> - <span v-if="phone"><i class="icon-phone-outline"></i> {{ phone }}</span> - </div> - <div v-if="country || city" class="location"> - <i class="icon-location"></i> - <strong v-if="city">{{ city }}</strong> - <em v-if="city">{{ country }}</em> + <div> + <small>{{ filteredOptions.length }}</small> + <v-select @search="handlerSearchOrganisation" + placeholder="Rechercher une structure" + :options="options" + label="label" + v-model="value" + :reduce="item => item.id" + :dropdown-should-open="dropdownShoultOpen" + @input="setSelected" + > + <template #list-header> + <li style="text-align: center"> + <label for="display_closed"> + Afficher les structures fermées + <input type="checkbox" v-model="displayClosed" id="display_closed" /> + </label> + </li> + </template> + + <template #option="{ id,code, shortname, longname, city, country, label, closed, email, phone }" + class="result-item"> + <div class="result-item" :class="{'organization-closed': closed }"> + <h4 style="margin: 0"> + <code v-if="code">{{ code }}</code> + <span> + <strong v-if="shortname">{{ shortname }}</strong> + <em v-if="longname">{{ longname }}</em> + </span> + </h4> + <div v-if="email || phone" class="infos"> + <span v-if="email"><i class="icon-mail"></i> {{ email }}</span> + <span v-if="phone"><i class="icon-phone-outline"></i> {{ phone }}</span> + </div> + <div v-if="country || city" class="location"> + <i class="icon-location"></i> + <strong v-if="city">{{ city }}</strong> + <em v-if="city">{{ country }}</em> + </div> </div> - </div> - </template> - </v-select> + </template> + </v-select> + </div> </template> <script> @@ -132,7 +136,7 @@ export default { if (this.delay != null) { clearTimeout(this.delay); } - this.delay = setTimeout(delayFunction, 1000); + this.delay = setTimeout(delayFunction, 300); } }, @@ -143,7 +147,10 @@ export default { * @param vm */ searchOrganization(loading, search, vm) { + let closeOpt = this.displayClosed ? '&active=' : '&active=ON' + + console.log("PRELOADVALUE:", this.preloadedValue); this.$http.get('/organization?l=m&q=' + encodeURI(search)).then( ok => { if (this.preloadedValue == false) { @@ -161,6 +168,10 @@ export default { } ) }, + dropdownShouldOpen(VueSelect) { + console.log("dropdownShouldOpen"); + return VueSelect.close; + }, } } </script> \ No newline at end of file diff --git a/module/Oscar/src/Oscar/Command/OscarOrganizationsSearchCommand.php b/module/Oscar/src/Oscar/Command/OscarOrganizationsSearchCommand.php index f32a581362c44ed6f960226dbb1374ce1a6a4d2a..49008e72e74738227e444df94904f118a2414f17 100644 --- a/module/Oscar/src/Oscar/Command/OscarOrganizationsSearchCommand.php +++ b/module/Oscar/src/Oscar/Command/OscarOrganizationsSearchCommand.php @@ -12,6 +12,7 @@ namespace Oscar\Command; use Moment\Moment; use Oscar\Entity\Authentification; use Oscar\Entity\LogActivity; +use Oscar\Entity\Organization; use Oscar\Entity\Person; use Oscar\Entity\Role; use Oscar\Service\ConnectorService; @@ -59,8 +60,13 @@ class OscarOrganizationsSearchCommand extends OscarCommandAbstract try { $search = $input->getArgument('search'); $organisations = $organisationService->search($search); + /** @var Organization $organisation */ foreach ($organisations as $organisation) { - $io->writeln(sprintf('- <bold>[%s]</bold> %s (%s)', $organisation->getId(), (string)$organisation, $organisation->getCode())); + $io->writeln(sprintf('- <bold>[%s]</bold> [%s] %s (%s)', + $organisation->getId(), + $organisation->getShortName(), + $organisation->getFullName(), + $organisation->getCode())); } } catch (\Exception $e ){ $io->error($e->getMessage() . "\n" . $e->getTraceAsString()); diff --git a/module/Oscar/src/Oscar/Strategy/Search/ActivityElasticSearch.php b/module/Oscar/src/Oscar/Strategy/Search/ActivityElasticSearch.php index e2a14cf55741845657ffa5d2faa7ad8e9413b0c4..69c88e12f106ba0d5a87c3f81c3b8eaaf0c9ab13 100644 --- a/module/Oscar/src/Oscar/Strategy/Search/ActivityElasticSearch.php +++ b/module/Oscar/src/Oscar/Strategy/Search/ActivityElasticSearch.php @@ -198,12 +198,13 @@ class ActivityElasticSearch implements ActivitySearchStrategy 'numbers^9', 'oscar^9', 'label^7', - 'description^7', + 'description^2', 'project^5', 'disciplines^5', 'activitytype^2', 'partners^5', - 'members^5'] + 'members^5'], + "fuzziness"=> "auto" ] ] ] diff --git a/module/Oscar/src/Oscar/Strategy/Search/OrganizationElasticSearch.php b/module/Oscar/src/Oscar/Strategy/Search/OrganizationElasticSearch.php index cbdf82dc9dc97c6e6163627b20facaf6d9826bf5..414a888f005bb9b8490bb39bac957b64ac318439 100644 --- a/module/Oscar/src/Oscar/Strategy/Search/OrganizationElasticSearch.php +++ b/module/Oscar/src/Oscar/Strategy/Search/OrganizationElasticSearch.php @@ -15,6 +15,7 @@ use Oscar\Connector\ConnectorRepport; use Oscar\Entity\ActivityOrganization; use Oscar\Entity\Organization; use Oscar\Entity\OrganizationPerson; +use Oscar\Exception\OscarException; class OrganizationElasticSearch implements OrganizationSearchStrategy { @@ -63,6 +64,8 @@ class OrganizationElasticSearch implements OrganizationSearchStrategy ->setHosts($this->getHosts()) ->build(); } + + return $this->elasticSearchClient; } @@ -173,11 +176,7 @@ class OrganizationElasticSearch implements OrganizationSearchStrategy 'country' => $organization->getCountry(), 'zipcode' => $organization->getZipCode(), 'description' => $organization->getDescription(), -// 'address1' => $organization->getStreet1(), -// 'address2' => $organization->getStreet2(), -// 'address3' => $organization->getStreet3(), 'siret' => $organization->getSiret(), - 'country' => $organization->getCountry(), 'persons' => $persons, 'activities' => $activities, 'connectors' => $connectors @@ -191,14 +190,12 @@ class OrganizationElasticSearch implements OrganizationSearchStrategy 'type' => $this->getType(), 'body' => [ 'size' => 10000, - - "query" => [ - 'query_string' => [ + 'multi_match' => [ 'fields' => [ - 'code^3', - 'shortname^4', - 'fullname^8', + 'code^7', + 'shortname^9', + 'fullname^5', 'description', 'email', 'city', @@ -209,53 +206,11 @@ class OrganizationElasticSearch implements OrganizationSearchStrategy 'persons', 'activities' ], + "fuzziness"=> "auto", 'query' => $search, ] -// "bool" => [ -// "should" => [ -// [ "match" => [ -// "code" => [ -// "query" => "$search", -// "boost" => 1 -// ] -// ]], -// [ "match" => [ -// "shortname" => [ -// "query" => "$search", -// "boost" => 10 -// ] -// ]], -// [ "match" => [ -// "fullname" => [ -// "query" => "$search", -// "boost" => 5 -// ] -// ]], -// ] -// ] ] - - - /* OFF - 'query' => [ - 'query_string' => [ - "search_fields" => [ - "shortname" => [ - "weight" => 10 - ], - "code" => [ - "weight" => 2 - ], - "fullname" => [ - "weight" => 2 - ], - ], - 'query' => $search, - 'use_dis_max' => true - ], - ] - /******/ ] ]; @@ -310,5 +265,77 @@ class OrganizationElasticSearch implements OrganizationSearchStrategy } catch (\Exception $e) { throw $e; } + + try { + $this->getClient()->indices()->create( + [ + 'index' => $this->getIndex(), + 'body' => [ + 'settings' => [ + 'analysis' => [ + 'analyzer' => [ + 'noaccent' => [ + "type" => "custom", + "tokenizer" => "standard", + "filter" => ['asciifolding', "lowercase"] + ] + ], + ] + ], + 'mappings' => [ + "organization" => [ + 'properties' => [ + 'code' => [ + 'type' => 'keyword', + ], + 'shortname' => [ + 'type' => 'text', +// 'analyzer' => 'noaccent' + ], + 'fullname' => [ +// 'analyzer' => 'noaccent', + 'type' => 'text', + ], + 'description' => [ +// 'analyzer' => 'noaccent', + 'type' => 'text', + ], + 'email' => [ +// 'analyzer' => 'noaccent', + 'type' => 'text', + ], + 'city' => [ +// 'analyzer' => 'noaccent', + 'type' => 'text', + ], + 'siret' => [ + 'type' => 'keyword', + ], + 'country' => [ + 'type' => 'keyword', + ], + 'connectors' => [ + 'type' => 'keyword', + ], + 'zipcode' => [ + 'type' => 'keyword', + ], + 'persons' => [ +// 'analyzer' => 'noaccent', + 'type' => 'text', + ], + 'activities' => [ +// 'analyzer' => 'noaccent', + 'type' => 'text', + ], + ] + ] + ] + ] + ] + ); + } catch (\Exception $e) { + throw new OscarException("Impossible de créer l'index de recherche : \n---\n" . $e->getMessage()); + } } } \ No newline at end of file diff --git a/module/Oscar/src/Oscar/Strategy/Search/PersonElasticSearch.php b/module/Oscar/src/Oscar/Strategy/Search/PersonElasticSearch.php index ecf2bf61056c3c771cab57ea3fc66964155da3f1..efd22fce0c1b44a0d5494b9e65c70bec4e8fb996 100644 --- a/module/Oscar/src/Oscar/Strategy/Search/PersonElasticSearch.php +++ b/module/Oscar/src/Oscar/Strategy/Search/PersonElasticSearch.php @@ -91,7 +91,7 @@ class PersonElasticSearch implements PersonSearchStrategy 'body' => [ 'size' => 10000, 'query' => [ - 'query_string' => [ + 'multi_match' => [ 'query' => $searchQuery, 'fields' => [ 'fullname^4', @@ -102,23 +102,12 @@ class PersonElasticSearch implements PersonSearchStrategy 'affectation^5', 'organizations^5', 'activities^5', - 'connectors'] + 'connectors' + ], + "fuzziness"=> "auto" ] ] ] - -// 'body' => [ -// 'size' => $limit, -// 'query' => [ -// 'multi_match' => [ -// 'query' => $searchQuery, -// 'type' => 'phrase_prefix', -// 'fields' => ['fullname^6','lastname^5', 'firstname^2', 'email', 'affectation^3', 'location^3', 'organizations', 'activities', 'connectors'], -// /* 'max_expansions' => 20,*/ -// /*'fuzziness' => 1*/ -// ] -// ] -// ] ]; $response = $this->getClient()->search($params);