diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index bb71762235a1187989c66f732efe2aa222b128a2..8396a9ed144b0d4185a8bfd0dd085c5ceac7eade 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -46,6 +46,7 @@ test:
     - export GHOST_HOST_AND_PORT=http://localhost:2368
     - export GHOST_ADMIN_API_KEY=60142bc9e33940000156bccc:6217742e2671e322612e89cac9bab61fcd01822709fe5d8f5e6a5b3e54d5e6bb
     - export SALT=$TEST_SALT
+    - export ELASTICSEARCH_NODE=http://localhost:9200
   script:
     - npm i
     - npm run test:cov
diff --git a/docker-compose.yml b/docker-compose.yml
index e95e22ec421be34eadca84b2076cc2b029fd0cb0..2f38db773589f3cc656c801e7054a97b65b43286 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -67,6 +67,43 @@ services:
     volumes:
       - db-ghost
 
+  es01:
+    image: elasticsearch:7.6.1
+    restart: unless-stopped
+    environment:
+      node.name: es01
+      cluster.name: es-docker-cluster
+      discovery.type: single-node
+      xpack.security.enabled: ${ELASTIC_SECURITY}
+      ELASTIC_PASSWORD: ${ELASTICSEARCH_PASSWORD}
+    volumes:
+      - db-elastic
+    networks:
+      - elastic
+    ports:
+      - ${ELASTICSEARCH_PORT}:9200
+
+  kib01:
+    image: docker.elastic.co/kibana/kibana:7.6.1
+    restart: unless-stopped
+    container_name: kib01
+    ports:
+      - ${KIBANA_PORT}:5601
+    environment:
+      ELASTICSEARCH_URL: http://es01:9200
+      ELASTICSEARCH_HOSTS: '["http://es01:9200"]'
+      ELASTICSEARCH_USERNAME: elastic
+      ELASTICSEARCH_PASSWORD: ${ELASTICSEARCH_PASSWORD}
+    depends_on:
+      - es01
+    networks:
+      - elastic
+
 volumes:
   db-ram:
   db-ghost:
+  db-elastic:
+
+networks:
+  elastic:
+    driver: bridge
diff --git a/package-lock.json b/package-lock.json
index d787d4c561026f1861332126e9218bc649e0b94c..ec29f08e932c0f4fe96f84d2de0a17c7a942e318 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -636,6 +636,40 @@
         "minimist": "^1.2.0"
       }
     },
+    "@elastic/elasticsearch": {
+      "version": "7.12.0",
+      "resolved": "https://registry.npmjs.org/@elastic/elasticsearch/-/elasticsearch-7.12.0.tgz",
+      "integrity": "sha512-GquUEytCijFRPEk3DKkkDdyhspB3qbucVQOwih9uNyz3iz804I+nGBUsFo2LwVvLQmQfEM0IY2+yoYfEz5wMug==",
+      "requires": {
+        "debug": "^4.3.1",
+        "hpagent": "^0.1.1",
+        "ms": "^2.1.3",
+        "pump": "^3.0.0",
+        "secure-json-parse": "^2.3.1"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "4.3.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
+          "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
+          "requires": {
+            "ms": "2.1.2"
+          },
+          "dependencies": {
+            "ms": {
+              "version": "2.1.2",
+              "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+              "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+            }
+          }
+        },
+        "ms": {
+          "version": "2.1.3",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+          "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+        }
+      }
+    },
     "@eslint/eslintrc": {
       "version": "0.2.1",
       "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.2.1.tgz",
@@ -1356,6 +1390,26 @@
         }
       }
     },
+    "@nestjs/config": {
+      "version": "0.6.3",
+      "resolved": "https://registry.npmjs.org/@nestjs/config/-/config-0.6.3.tgz",
+      "integrity": "sha512-JxvvUpmH0/WOrTB+zh8dEkxSUQXhB7V3d/qeQXyCnMiEFjaq89+fNFztpWjz4DlOfdS4/eYTzIEy9PH2uGnfzA==",
+      "requires": {
+        "dotenv": "8.2.0",
+        "dotenv-expand": "5.1.0",
+        "lodash.get": "4.4.2",
+        "lodash.has": "4.5.2",
+        "lodash.set": "4.3.2",
+        "uuid": "8.3.2"
+      },
+      "dependencies": {
+        "uuid": {
+          "version": "8.3.2",
+          "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+          "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
+        }
+      }
+    },
     "@nestjs/core": {
       "version": "7.5.1",
       "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-7.5.1.tgz",
@@ -1370,6 +1424,11 @@
         "uuid": "8.3.1"
       }
     },
+    "@nestjs/elasticsearch": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/@nestjs/elasticsearch/-/elasticsearch-7.1.0.tgz",
+      "integrity": "sha512-3ixmu9MkTh0DS+LKAKcWHLyf/1DPQTXoy+aVClVI14DJQU208oHR3V0e9klApC+GXCYW+BDhNReh4HRyekjTrw=="
+    },
     "@nestjs/jwt": {
       "version": "7.2.0",
       "resolved": "https://registry.npmjs.org/@nestjs/jwt/-/jwt-7.2.0.tgz",
@@ -4921,6 +4980,11 @@
       "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
       "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw=="
     },
+    "dotenv-expand": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
+      "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA=="
+    },
     "dotgitignore": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz",
@@ -5060,7 +5124,6 @@
       "version": "1.4.4",
       "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
       "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
-      "dev": true,
       "requires": {
         "once": "^1.4.0"
       }
@@ -6941,6 +7004,11 @@
       "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
       "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg=="
     },
+    "hpagent": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-0.1.1.tgz",
+      "integrity": "sha512-IxJWQiY0vmEjetHdoE9HZjD4Cx+mYTr25tR7JCxXaiI3QxW0YqYyM11KyZbHufoa/piWhMb2+D3FGpMgmA2cFQ=="
+    },
     "html-encoding-sniffer": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz",
@@ -8183,6 +8251,7 @@
       "version": "12.0.0",
       "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-12.0.0.tgz",
       "integrity": "sha512-+8K35LlboWiPuCnXSyiid7rFdxNlpCWWM20WEYe6IZH6psfUWKZmSpSRQ5tk0C0cBeDsvsnIzcef5mYhyJsbug==",
+      "dev": true,
       "requires": {
         "mkdirp": "^1.0.4",
         "strip-ansi": "^5.2.0",
@@ -8193,17 +8262,20 @@
         "ansi-regex": {
           "version": "4.1.0",
           "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
-          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
+          "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+          "dev": true
         },
         "mkdirp": {
           "version": "1.0.4",
           "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
-          "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
+          "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+          "dev": true
         },
         "strip-ansi": {
           "version": "5.2.0",
           "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
           "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+          "dev": true,
           "requires": {
             "ansi-regex": "^4.1.0"
           }
@@ -8211,7 +8283,8 @@
         "uuid": {
           "version": "3.4.0",
           "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
-          "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
+          "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
+          "dev": true
         }
       }
     },
@@ -9288,6 +9361,16 @@
       "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
       "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0="
     },
+    "lodash.get": {
+      "version": "4.4.2",
+      "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+      "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
+    },
+    "lodash.has": {
+      "version": "4.5.2",
+      "resolved": "https://registry.npmjs.org/lodash.has/-/lodash.has-4.5.2.tgz",
+      "integrity": "sha1-0Z9NwQlQWMzL4rDN9O4P5Ko3yGI="
+    },
     "lodash.includes": {
       "version": "4.3.0",
       "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
@@ -9334,6 +9417,11 @@
       "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
       "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
     },
+    "lodash.set": {
+      "version": "4.3.2",
+      "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz",
+      "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM="
+    },
     "lodash.sortby": {
       "version": "4.7.0",
       "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
@@ -11158,7 +11246,6 @@
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
       "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
-      "dev": true,
       "requires": {
         "end-of-stream": "^1.1.0",
         "once": "^1.3.1"
@@ -11806,6 +11893,11 @@
         "ajv-keywords": "^3.4.1"
       }
     },
+    "secure-json-parse": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.4.0.tgz",
+      "integrity": "sha512-Q5Z/97nbON5t/L/sH6mY2EacfjVGwrCcSi5D3btRO2GZ8pf1K1UN7Z9H5J57hjVU2Qzxr1xO+FmBhOvEkzCMmg=="
+    },
     "semver": {
       "version": "7.3.2",
       "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
@@ -14176,7 +14268,8 @@
     "xml": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
-      "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU="
+      "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=",
+      "dev": true
     },
     "xml-name-validator": {
       "version": "3.0.0",
diff --git a/package.json b/package.json
index 79114f2ed061d6b141ac421bafe63a3df12d5d55..2f017979e39aebaecae276d4a32e1b44161f660c 100644
--- a/package.json
+++ b/package.json
@@ -25,8 +25,11 @@
     "migrate:down": "migrate --migrations-dir=\"./src/migrations/scripts\" --compiler=\"ts:./src/migrations/migrations-utils/ts-compiler.js\" down"
   },
   "dependencies": {
+    "@elastic/elasticsearch": "^7.12.0",
     "@nestjs/common": "^7.6.13",
+    "@nestjs/config": "^0.6.3",
     "@nestjs/core": "^7.5.1",
+    "@nestjs/elasticsearch": "^7.1.0",
     "@nestjs/jwt": "^7.2.0",
     "@nestjs/mongoose": "^7.1.0",
     "@nestjs/passport": "^7.1.5",
diff --git a/scripts/init-ghost.js b/scripts/init-ghost.js
index 350b0376602770cb6b9112cdb8afde728f6a13fe..345ed027d3792a0966ff63452cb05fddeb406fe1 100644
--- a/scripts/init-ghost.js
+++ b/scripts/init-ghost.js
@@ -81,8 +81,9 @@ function processImagesInHTML(html) {
   // Find images that Ghost Upload supports
   let imageRegex = /="([^"]*?(?:\.jpg|\.jpeg|\.gif|\.png|\.svg|\.sgvz))"/gim;
   let imagePromises = [];
+  let result;
 
-  while ((const result = imageRegex.exec(html)) !== null) {
+  while ((result = imageRegex.exec(html)) !== null) {
     let file = result[1];
     // Upload the image, using the original matched filename as a reference
     imagePromises.push(
diff --git a/src/admin/admin.controller.spec.ts b/src/admin/admin.controller.spec.ts
index 153f13440355cc1802e1aadd5d47d174e8fd5866..dc0bdef307a30973ed3864fa428e46aca34c8dea 100644
--- a/src/admin/admin.controller.spec.ts
+++ b/src/admin/admin.controller.spec.ts
@@ -5,8 +5,10 @@ import { ConfigurationModule } from '../configuration/configuration.module';
 import { MailerService } from '../mailer/mailer.service';
 import { NewsletterSubscription } from '../newsletter/newsletter-subscription.schema';
 import { NewsletterService } from '../newsletter/newsletter.service';
+import { SearchModule } from '../search/search.module';
 import { Structure } from '../structures/schemas/structure.schema';
 import { StructuresService } from '../structures/services/structures.service';
+import { StructuresSearchService } from '../structures/services/structures-search.service';
 import { User } from '../users/schemas/user.schema';
 import { UsersService } from '../users/users.service';
 import { AdminController } from './admin.controller';
@@ -17,10 +19,11 @@ describe('AdminController', () => {
 
   beforeEach(async () => {
     const module: TestingModule = await Test.createTestingModule({
-      imports: [ConfigurationModule, HttpModule],
+      imports: [ConfigurationModule, HttpModule, SearchModule],
       providers: [
         UsersService,
         StructuresService,
+        StructuresSearchService,
         NewsletterService,
         MailerService,
         {
diff --git a/src/search/search.module.ts b/src/search/search.module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8e9b5e85b2226d75c157886fe06eabf64c265d7b
--- /dev/null
+++ b/src/search/search.module.ts
@@ -0,0 +1,22 @@
+import { Module } from '@nestjs/common';
+import { ConfigModule, ConfigService } from '@nestjs/config';
+import { ElasticsearchModule } from '@nestjs/elasticsearch';
+
+@Module({
+  imports: [
+    ConfigModule,
+    ElasticsearchModule.registerAsync({
+      imports: [ConfigModule],
+      useFactory: async (configService: ConfigService) => ({
+        node: configService.get('ELASTICSEARCH_NODE'),
+        auth: {
+          username: configService.get('ELASTICSEARCH_USERNAME'),
+          password: configService.get('ELASTICSEARCH_PASSWORD'),
+        },
+      }),
+      inject: [ConfigService],
+    }),
+  ],
+  exports: [ElasticsearchModule],
+})
+export class SearchModule {}
diff --git a/src/structures/interfaces/structure-search-body.interface.ts b/src/structures/interfaces/structure-search-body.interface.ts
new file mode 100644
index 0000000000000000000000000000000000000000..24d7591930d82643cd181ced7132665d8d2007d9
--- /dev/null
+++ b/src/structures/interfaces/structure-search-body.interface.ts
@@ -0,0 +1,8 @@
+import { Address } from '../schemas/address.schema';
+
+export interface StructureSearchBody {
+  structureId: string;
+  structureName: string;
+  structureType: string;
+  address: Address;
+}
diff --git a/src/structures/interfaces/structure-search-response.interface.ts b/src/structures/interfaces/structure-search-response.interface.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7497343827756c4a16df4e15a861709604a00ce0
--- /dev/null
+++ b/src/structures/interfaces/structure-search-response.interface.ts
@@ -0,0 +1,10 @@
+import { StructureSearchBody } from './structure-search-body.interface';
+
+export interface StructureSearchResult {
+  hits: {
+    total: number;
+    hits: Array<{
+      _source: StructureSearchBody;
+    }>;
+  };
+}
diff --git a/src/structures/services/structures-search.service.ts b/src/structures/services/structures-search.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f334926a9fce19a953801764b1812f906692557d
--- /dev/null
+++ b/src/structures/services/structures-search.service.ts
@@ -0,0 +1,91 @@
+import { Injectable } from '@nestjs/common';
+import { ElasticsearchService } from '@nestjs/elasticsearch';
+import { structureDto } from '../dto/structure.dto';
+import { StructureDocument } from '../schemas/structure.schema';
+import { StructureSearchBody } from '../interfaces/structure-search-body.interface';
+import { StructureSearchResult } from '../interfaces/structure-search-response.interface';
+
+@Injectable()
+export class StructuresSearchService {
+  private index = 'structures';
+
+  constructor(private readonly elasticsearchService: ElasticsearchService) {}
+
+  public async indexStructure(structure: StructureDocument): Promise<StructureDocument> {
+    this.elasticsearchService.index<StructureSearchResult, StructureSearchBody>({
+      index: this.index,
+      id: structure._id,
+      body: {
+        structureName: structure.structureName,
+        structureType: structure.structureType,
+        structureId: structure._id,
+        address: structure.address,
+      },
+    });
+    return structure;
+  }
+
+  public async createStructureIndex(): Promise<any> {
+    return await this.elasticsearchService.indices.create({
+      index: this.index,
+    });
+  }
+
+  public async dropIndex(): Promise<any> {
+    if (
+      (
+        await this.elasticsearchService.indices.exists({
+          index: this.index,
+        })
+      ).body
+    ) {
+      return this.elasticsearchService.indices.delete({
+        index: this.index,
+      });
+    }
+  }
+
+  public async deleteIndexStructure(structure: StructureDocument): Promise<StructureDocument> {
+    this.elasticsearchService.delete<StructureSearchResult, StructureSearchBody>({
+      index: this.index,
+      id: structure._id,
+    });
+    return structure;
+  }
+
+  public async search(searchString: string): Promise<StructureSearchBody[]> {
+    searchString = searchString ? searchString + '*' : '*';
+    const { body } = await this.elasticsearchService.search<StructureSearchResult>({
+      index: this.index,
+      body: {
+        from: 0,
+        size: 30,
+        query: {
+          query_string: {
+            analyze_wildcard: 'true',
+            query: searchString,
+            fields: ['structureName^5', 'structureType^5', 'address.street', 'address.commune^5'],
+            fuzziness: 'AUTO',
+          },
+        },
+      },
+    });
+    const hits = body.hits.hits;
+    return hits.map((item) => item._source);
+  }
+
+  public async update(structure: structureDto, id: string): Promise<any> {
+    return this.elasticsearchService.update({
+      index: this.index,
+      id: id,
+      body: {
+        doc: {
+          structureName: structure.structureName,
+          structureType: structure.structureType,
+          structureId: id,
+          address: structure.address,
+        },
+      },
+    });
+  }
+}
diff --git a/src/structures/services/structures.service.ts b/src/structures/services/structures.service.ts
index c6c02b27a8c0c0ba0fd1ccc298a288bc98263c0c..8b98603ab518083513dd8553994e794e897592a0 100644
--- a/src/structures/services/structures.service.ts
+++ b/src/structures/services/structures.service.ts
@@ -14,6 +14,7 @@ import { DateTime } from 'luxon';
 import { IUser } from '../../users/interfaces/user.interface';
 import * as _ from 'lodash';
 import { OwnerDto } from '../../users/dto/owner.dto';
+import { StructuresSearchService } from './structures-search.service';
 import { CategoriesFormationsModule } from '../../categories/schemas/categoriesFormationsModule.schema';
 import { CategoriesModule } from '../../categories/categories.module';
 import { CategoriesAccompagnement } from '../../categories/schemas/categoriesAccompagnement.schema';
@@ -26,9 +27,43 @@ export class StructuresService {
     private readonly httpService: HttpService,
     private readonly userService: UsersService,
     private readonly mailerService: MailerService,
+    private structuresSearchService: StructuresSearchService,
     @InjectModel(Structure.name) private structureModel: Model<StructureDocument>
   ) {}
 
+  async initiateStructureIndex(): Promise<StructureDocument[]> {
+    await this.structuresSearchService.dropIndex();
+    await this.structuresSearchService.createStructureIndex();
+    return this.populateES();
+  }
+
+  async searchForStructures(text: string, filters?: Array<any>): Promise<StructureDocument[]> {
+    const results = await this.structuresSearchService.search(text);
+    const ids = results.map((result) => result.structureId);
+    if (!ids.length) {
+      return [];
+    }
+    //we match ids from Elasticsearch with ids from mongoDB (and filters) and sort the result according to ElasticSearch order.
+    if (filters.length > 0) {
+      return (
+        await this.structureModel
+          .find({
+            _id: { $in: ids },
+            $and: [...this.parseFilter(filters), { deletedAt: { $exists: false }, accountVerified: true }],
+          })
+          .exec()
+      ).sort((a, b) => ids.indexOf(a.id) - ids.indexOf(b.id));
+    } else {
+      return (
+        await this.structureModel
+          .find({
+            _id: { $in: ids },
+          })
+          .exec()
+      ).sort((a, b) => ids.indexOf(a.id) - ids.indexOf(b.id));
+    }
+  }
+
   public async create(idUser: string, structure: structureDto): Promise<Structure> {
     const user = await this.userService.findOne(idUser);
     if (!user) {
@@ -37,10 +72,15 @@ export class StructuresService {
     const createdStructure = new this.structureModel(structure);
     createdStructure._id = Types.ObjectId();
     await createdStructure.save();
-    await this.getStructurePosition(createdStructure).then((postition: StructureDocument) => {
-      return this.structureModel
-        .findByIdAndUpdate(Types.ObjectId(createdStructure._id), { address: postition.address, coord: postition.coord })
-        .exec();
+    await this.getStructurePosition(createdStructure).then(async (postition: StructureDocument) => {
+      return this.structuresSearchService.indexStructure(
+        await this.structureModel
+          .findByIdAndUpdate(Types.ObjectId(createdStructure._id), {
+            address: postition.address,
+            coord: postition.coord,
+          })
+          .exec()
+      );
     });
     user.structuresLink.push(createdStructure._id);
     user.save();
@@ -111,6 +151,16 @@ export class StructuresService {
     return this.structureModel.find({ deletedAt: { $exists: false }, accountVerified: true }).exec();
   }
 
+  public async populateES(): Promise<StructureDocument[]> {
+    const structures = await this.structureModel.find({ deletedAt: { $exists: false } }).exec();
+    await Promise.all(
+      structures.map((structure: StructureDocument) => {
+        this.structuresSearchService.indexStructure(structure);
+      })
+    );
+    return structures;
+  }
+  
   public async findAllFormated(
     formationCategories: CategoriesFormations[],
     accompagnementCategories: CategoriesAccompagnement[],
@@ -213,6 +263,7 @@ export class StructuresService {
     if (!result) {
       throw new HttpException('Invalid structure id', HttpStatus.BAD_REQUEST);
     } else {
+      await this.structuresSearchService.update(structure, idStructure);
       this.sendAdminStructureNotification(
         result,
         this.mailerService.config.templates.structureModificationNotification.ejs,
@@ -335,6 +386,7 @@ export class StructuresService {
     if (!structure) {
       throw new HttpException('Invalid structure id', HttpStatus.BAD_REQUEST);
     }
+    this.structuresSearchService.deleteIndexStructure(structure);
     structure.structureType = null;
     structure.deletedAt = DateTime.local().setZone('Europe/Paris').toString();
     this.anonymizeStructure(structure).save();
diff --git a/src/structures/structures.controller.ts b/src/structures/structures.controller.ts
index 9c6283a24c247d06648ad25c9cb883cf8189b84c..3121e59c81b2a83e1b6caf36e6df3ca36ffb9401 100644
--- a/src/structures/structures.controller.ts
+++ b/src/structures/structures.controller.ts
@@ -27,8 +27,9 @@ import { UsersService } from '../users/users.service';
 import { CreateStructureDto } from './dto/create-structure.dto';
 import { QueryStructure } from './dto/query-structure.dto';
 import { structureDto } from './dto/structure.dto';
-import { Structure } from './schemas/structure.schema';
+import { Structure, StructureDocument } from './schemas/structure.schema';
 import { StructuresService } from './services/structures.service';
+import { StructureSearchBody } from './interfaces/structure-search-body.interface';
 
 @Controller('structures')
 export class StructuresController {
@@ -65,7 +66,12 @@ export class StructuresController {
 
   @Post('search')
   public async search(@Query() query: QueryStructure, @Body() body): Promise<Structure[]> {
-    return this.structureService.search(query.query, body ? body.filters : null);
+    return await this.structureService.searchForStructures(query.query, body ? body.filters : null);
+  }
+
+  @Post('resetSearchIndex')
+  public async resetES(): Promise<StructureDocument[]> {
+    return this.structureService.initiateStructureIndex();
   }
 
   @Put('updateAfterOwnerVerify/:id')
diff --git a/src/structures/structures.module.ts b/src/structures/structures.module.ts
index 1445999d289ff826e1504e3754d814f10ed06322..650e3adfd9b7ef57e13d8e06090f1b9100f26e33 100644
--- a/src/structures/structures.module.ts
+++ b/src/structures/structures.module.ts
@@ -11,6 +11,8 @@ import { StructureTypeController } from './structure-type/structure-type.control
 import { StructureTypeService } from './structure-type/structure-type.service';
 import { StructureType, StructureTypeSchema } from './structure-type/structure-type.schema';
 import { CategoriesModule } from '../categories/categories.module';
+import { StructuresSearchService } from './services/structures-search.service';
+import { SearchModule } from '../search/search.module';
 
 @Module({
   imports: [
@@ -23,9 +25,10 @@ import { CategoriesModule } from '../categories/categories.module';
     forwardRef(() => UsersModule),
     CategoriesModule,
     TempUserModule,
+    SearchModule,
   ],
   controllers: [StructuresController, StructureTypeController],
   exports: [StructuresService, StructureTypeService],
-  providers: [StructuresService, StructureTypeService, ApticStructuresService],
+  providers: [StructuresSearchService, StructuresService, StructureTypeService, ApticStructuresService],
 })
 export class StructuresModule {}
diff --git a/src/users/users.controller.spec.ts b/src/users/users.controller.spec.ts
index e9c8b75b5ae7a6a0e434e1faca9ef95c71bbefb5..68da5450f95300fde9828f6a2ad2d1905b738753 100644
--- a/src/users/users.controller.spec.ts
+++ b/src/users/users.controller.spec.ts
@@ -4,8 +4,10 @@ import { Test, TestingModule } from '@nestjs/testing';
 import { CategoriesModule } from '../categories/categories.module';
 import { ConfigurationModule } from '../configuration/configuration.module';
 import { MailerService } from '../mailer/mailer.service';
+import { SearchModule } from '../search/search.module';
 import { Structure } from '../structures/schemas/structure.schema';
 import { StructuresService } from '../structures/services/structures.service';
+import { StructuresSearchService } from '../structures/services/structures-search.service';
 import { TempUser } from '../temp-user/temp-user.schema';
 import { TempUserService } from '../temp-user/temp-user.service';
 import { User } from './schemas/user.schema';
@@ -17,10 +19,11 @@ describe('UsersController', () => {
 
   beforeEach(async () => {
     const module: TestingModule = await Test.createTestingModule({
-      imports: [ConfigurationModule, HttpModule],
+      imports: [ConfigurationModule, HttpModule, SearchModule],
       providers: [
         UsersService,
         StructuresService,
+        StructuresSearchService,
         MailerService,
         TempUserService,
         {
diff --git a/template.env b/template.env
index 41cb576d15639e668ff90bbdadc2e508f70a9e03..027d8b6a62352ab2d9b95ae9c6d337d9e19d13c6 100644
--- a/template.env
+++ b/template.env
@@ -20,3 +20,10 @@ GHOST_CONTENT_API_KEY=<Ghost global api key, can be found in integration part of
 GHOST_ADMIN_API_KEY=<Ghost admin api key, can be found in integration part of ghost UI>
 GHOST_HOST_AND_PORT=<Ghost host and port, ex:http://localhost:2368>
 USER_PWD=<test user password, this password will be user by every test users>
+ELASTICSEARCH_NODE=<elastic search container node>
+ELASTICSEARCH_PATH=<elastic search container path>
+ELASTICSEARCH_PORT=<elastic search port>
+ELASTICSEARCH_USERNAME=<elastic search username>
+ELASTICSEARCH_PASSWORD=<elastic search password>
+ELASTIC_SECURITY=<elastic search security boolean (true = secure)>
+KIBANA_PORT=<kibana port>
\ No newline at end of file