diff --git a/package-lock.json b/package-lock.json
index f10f9a2a45196ae95f7889d264d1cf2c5a19755b..2393a08417e23f492a977a8607d146de5c1dea34 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2340,7 +2340,7 @@
         "object-assign": {
           "version": "4.1.1",
           "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
-          "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+          "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
           "dev": true
         },
         "proxy-middleware": {
diff --git a/package.json b/package.json
index eebbecb226b9c83119f81144dabab412784edee3..218ba105a0470e3f8c7c647e049ee393a8cc339e 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,7 @@
     "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
     "release": "standard-version",
     "init-db": "node ./scripts/init-db.js",
-    "test": "jest",
+    "test": "jest --config ./test/jest.json --coverage",
     "test:watch": "jest --config ./test/jest.json --watch --coverage",
     "test:cov": "jest --config ./test/jest.json --coverage --ci --reporters=default --reporters=jest-junit",
     "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
diff --git a/scripts/data/employers.js b/scripts/data/employers.js
new file mode 100644
index 0000000000000000000000000000000000000000..74be23fb24eb7a6ac645cc00ad167c10d64b4da7
--- /dev/null
+++ b/scripts/data/employers.js
@@ -0,0 +1,112 @@
+// eslint-disable-next-line @typescript-eslint/no-var-requires
+const mongoose = require('mongoose');
+
+module.exports = {
+  data: [
+    {
+      _id: mongoose.Types.ObjectId('6285289d02c9259438c802d3'),
+      name: 'Association',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('62867faf7a5b13480c22b2fc'),
+      name: 'CAF',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('628dfc353a0f370acc450ac3'),
+      name: 'CARSAT',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('628dfc353a0f370acc450ac4'),
+      name: 'CCAS',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('628dfc353a0f370acc450ac5'),
+      name: 'CPAM',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('628dfc353a0f370acc450ac6'),
+      name: 'Centre socio-culturel',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('628dfc353a0f370acc450ac7'),
+      name: 'Cyberbase',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('628dfc353a0f370acc450ac8'),
+      name: 'Espace de coworking',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('628dfc353a0f370acc450ac9'),
+      name: 'Fablab',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('627b6ca899862168705ca830'),
+      name: 'MJC',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('627b6ca899862168705ca831'),
+      name: 'Mairie',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('627b6ca899862168705ca832'),
+      name: 'Maison France Service',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('627b6ca899862168705ca833'),
+      name: 'Missions locales',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('627b6ca899862168705ca834'),
+      name: 'Médiathèque / Bibliothèque',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('627b6ca899862168705ca835'),
+      name: 'Métropole de Lyon',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('627b6ca899862168705ca836'),
+      name: 'Pimms',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('627b6ca899862168705ca837'),
+      name: 'Pôle emploi',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('627b6ca899862168705ca838'),
+      name: 'Ressourcerie',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('627b6ca899862168705ca839'),
+      name: "Structure d'insertion",
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('627b6ca899862168705ca83a'),
+      name: 'Structure de formation',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('627b6ca899862168705ca83b'),
+      name: 'Structure information jeunesse (SIJ)',
+      validated: true,
+    },
+  ],
+};
diff --git a/scripts/data/jobs.js b/scripts/data/jobs.js
new file mode 100644
index 0000000000000000000000000000000000000000..01d5076cca78f620c8f7cf975d1d781683360566
--- /dev/null
+++ b/scripts/data/jobs.js
@@ -0,0 +1,49 @@
+// eslint-disable-next-line @typescript-eslint/no-var-requires
+const mongoose = require('mongoose');
+
+module.exports = {
+  data: [
+    {
+      _id: mongoose.Types.ObjectId('627b6ca899862168705ca845'),
+      hasPersonalOffer: true,
+      name: 'Formateur',
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('627b6ca899862168705ca846'),
+      name: 'CNFS',
+      hasPersonalOffer: true,
+      validated: true,
+    },
+    {
+      _id: mongoose.Types.ObjectId('627b6ca899862168705ca847'),
+      hasPersonalOffer: true,
+      name: 'Médiateur numérique',
+      validated: true,
+    },
+    {
+      hasPersonalOffer: false,
+      _id: mongoose.Types.ObjectId('627b6ca899862168705ca848'),
+      name: 'Travailleur social',
+      validated: true,
+    },
+    {
+      hasPersonalOffer: false,
+      _id: mongoose.Types.ObjectId('627b6ca899862168705ca849'),
+      name: 'Conseiller',
+      validated: true,
+    },
+    {
+      hasPersonalOffer: false,
+      _id: mongoose.Types.ObjectId('627b6ca899862168705ca84a'),
+      name: 'Chef de projet',
+      validated: true,
+    },
+    {
+      hasPersonalOffer: false,
+      _id: mongoose.Types.ObjectId('6283603c51d1098fd4a8facf'),
+      name: 'Élu',
+      validated: true,
+    },
+  ],
+};
diff --git a/scripts/data/users.js b/scripts/data/users.js
index fb5ebc814ed025c1c234f379aa67412d9f4f7be2..0ca9299accd0820ad23df9f5e9ccd878802a0b24 100644
--- a/scripts/data/users.js
+++ b/scripts/data/users.js
@@ -17,6 +17,8 @@ module.exports = {
       emailVerified: true,
       email: 'admin@admin.com',
       structureOutdatedMailSent: [],
+      employer: mongoose.Types.ObjectId('627b6ca899862168705ca836'),
+      job: mongoose.Types.ObjectId('627b6ca899862168705ca846'),
     },
     {
       structureOutdatedMailSent: [],
@@ -28,10 +30,12 @@ module.exports = {
       resetPasswordToken: null,
       validationToken: null,
       emailVerified: true,
-      email: 'paula.dubois@mii.com',
+      email: 'paula.dubois@test.com',
       name: 'Paula',
       surname: 'DUBOIS',
       phone: '06 07 08 09 10',
+      employer: mongoose.Types.ObjectId('627b6ca899862168705ca836'),
+      job: mongoose.Types.ObjectId('627b6ca899862168705ca846'),
     },
     {
       structureOutdatedMailSent: [],
@@ -52,6 +56,128 @@ module.exports = {
       name: 'Jean-Paul',
       surname: 'DESCHAMPS',
       phone: '06 11 11 11 11',
+      employer: mongoose.Types.ObjectId('627b6ca899862168705ca835'),
+      job: mongoose.Types.ObjectId('627b6ca899862168705ca848'),
+    },
+    {
+      structureOutdatedMailSent: [],
+      pendingStructuresLink: [],
+      structuresLink: [
+        mongoose.Types.ObjectId('61e9260c2ac971550065e262'),
+        mongoose.Types.ObjectId('61e9260b2ac971550065e261'),
+      ],
+      newEmail: null,
+      changeEmailToken: null,
+      role: 0,
+      resetPasswordToken: null,
+      validationToken: null,
+      emailVerified: true,
+      email: 'marine.ducanal@test.com',
+      name: 'Marine',
+      surname: 'DUCANAL',
+      phone: '06 11 11 11 11',
+      employer: mongoose.Types.ObjectId('627b6ca899862168705ca837'),
+      job: mongoose.Types.ObjectId('627b6ca899862168705ca848'),
+    },
+    {
+      structureOutdatedMailSent: [],
+      pendingStructuresLink: [],
+      structuresLink: [
+        mongoose.Types.ObjectId('61e9260c2ac971550065e262'),
+        mongoose.Types.ObjectId('61e9260b2ac971550065e261'),
+      ],
+      newEmail: null,
+      changeEmailToken: null,
+      role: 0,
+      resetPasswordToken: null,
+      validationToken: null,
+      emailVerified: true,
+      email: 'hugo.nouts@test.com',
+      name: 'Hugo',
+      surname: 'NOUTS',
+      phone: '06 11 11 11 11',
+      employer: mongoose.Types.ObjectId('627b6ca899862168705ca833'),
+      job: mongoose.Types.ObjectId('627b6ca899862168705ca846'),
+    },
+    {
+      structureOutdatedMailSent: [],
+      pendingStructuresLink: [],
+      structuresLink: [
+        mongoose.Types.ObjectId('61e9260c2ac971550065e262'),
+        mongoose.Types.ObjectId('61e9260b2ac971550065e261'),
+      ],
+      newEmail: null,
+      changeEmailToken: null,
+      role: 0,
+      resetPasswordToken: null,
+      validationToken: null,
+      emailVerified: true,
+      email: 'bastien.dumont@test.com',
+      name: 'Bastien',
+      surname: 'DUMONT',
+      phone: '06 11 11 11 11',
+      employer: mongoose.Types.ObjectId('627b6ca899862168705ca835'),
+      job: mongoose.Types.ObjectId('627b6ca899862168705ca849'),
+    },
+    {
+      structureOutdatedMailSent: [],
+      pendingStructuresLink: [],
+      structuresLink: [
+        mongoose.Types.ObjectId('61e9260c2ac971550065e262'),
+        mongoose.Types.ObjectId('61e9260b2ac971550065e261'),
+      ],
+      newEmail: null,
+      changeEmailToken: null,
+      role: 0,
+      resetPasswordToken: null,
+      validationToken: null,
+      emailVerified: true,
+      email: 'guilhem.carron@test.com',
+      name: 'Guilhem',
+      surname: 'CARRON',
+      phone: '06 11 11 11 11',
+      employer: mongoose.Types.ObjectId('627b6ca899862168705ca834'),
+      job: mongoose.Types.ObjectId('627b6ca899862168705ca848'),
+    },
+    {
+      structureOutdatedMailSent: [],
+      pendingStructuresLink: [],
+      structuresLink: [
+        mongoose.Types.ObjectId('61e9260c2ac971550065e262'),
+        mongoose.Types.ObjectId('61e9260b2ac971550065e261'),
+      ],
+      newEmail: null,
+      changeEmailToken: null,
+      role: 0,
+      resetPasswordToken: null,
+      validationToken: null,
+      emailVerified: true,
+      email: 'hugo.subtil@test.com',
+      name: 'Hugo',
+      surname: 'SUBTIL',
+      phone: '06 11 11 11 11',
+      employer: mongoose.Types.ObjectId('627b6ca899862168705ca835'),
+      job: mongoose.Types.ObjectId('627b6ca899862168705ca846'),
+    },
+    {
+      structureOutdatedMailSent: [],
+      pendingStructuresLink: [],
+      structuresLink: [
+        mongoose.Types.ObjectId('61e9260c2ac971550065e262'),
+        mongoose.Types.ObjectId('61e9260b2ac971550065e261'),
+      ],
+      newEmail: null,
+      changeEmailToken: null,
+      role: 0,
+      resetPasswordToken: null,
+      validationToken: null,
+      emailVerified: true,
+      email: 'remi.pailharey@test.com',
+      name: 'Rémi',
+      surname: 'PAILHAREY',
+      phone: '06 11 11 11 11',
+      employer: mongoose.Types.ObjectId('627b6ca899862168705ca835'),
+      job: mongoose.Types.ObjectId('627b6ca899862168705ca845'),
     },
   ],
 };
diff --git a/scripts/init-db.js b/scripts/init-db.js
index 52c7ce70bb70524d78a66f44a1ede1ada701094a..2041dc2562be77a1e59d115dc7fe69aa162017af 100644
--- a/scripts/init-db.js
+++ b/scripts/init-db.js
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/no-var-requires */
 // eslint-disable-next-line @typescript-eslint/no-var-requires
 const mongoose = require('mongoose');
 // eslint-disable-next-line @typescript-eslint/no-var-requires
@@ -7,6 +8,8 @@ const categoriesOthersData = require('./data/categoriesOthers');
 const categoriesAccompanementsData = require('./data/categoriesAccompanements');
 const categoriesFormationData = require('./data/categoriesFormation');
 const structuresData = require('./data/structures');
+const jobsData = require('./data/jobs');
+const employersData = require('./data/employers');
 // eslint-disable-next-line @typescript-eslint/no-var-requires
 const bcrypt = require('bcrypt');
 // eslint-disable-next-line @typescript-eslint/no-var-requires
@@ -40,8 +43,9 @@ const handleError = async (name, err) => {
     else throw err;
   } else console.log(`-- ${name} collection dropped --`);
 };
+
 // define Schema
-var usersSchema = mongoose.Schema({
+const usersSchema = mongoose.Schema({
   name: String,
   surname: String,
   email: String,
@@ -56,30 +60,50 @@ var usersSchema = mongoose.Schema({
   pendingStructuresLink: [],
   password: String,
   phone: String,
+  employer: String,
+  job: String,
 });
-var structuresTypeSchema = mongoose.Schema(
+
+const jobsSchema = mongoose.Schema(
+  {
+    name: String,
+    hasPersonalOffer: Boolean,
+    validated: Boolean,
+  },
+  { collection: 'jobs' }
+);
+
+const employersSchema = mongoose.Schema(
+  {
+    name: String,
+    validated: Boolean,
+  },
+  { collection: 'employers' }
+);
+
+const structuresTypeSchema = mongoose.Schema(
   {
     name: String,
     values: [],
   },
   { collection: 'structuretype' }
 );
-var categoriesOthersSchema = mongoose.Schema({
+const categoriesOthersSchema = mongoose.Schema({
   name: String,
   id: String,
   modules: [],
 });
-var categoriesAccompanementsSchema = mongoose.Schema({
+const categoriesAccompanementsSchema = mongoose.Schema({
   name: String,
   id: String,
   modules: [],
 });
-var categoriesFormationSchema = mongoose.Schema({
+const categoriesFormationSchema = mongoose.Schema({
   name: String,
   id: String,
   modules: [],
 });
-var structuresSchema = mongoose.Schema({
+const structuresSchema = mongoose.Schema({
   numero: String,
   createdAt: String,
   updatedAt: String,
@@ -123,12 +147,14 @@ var structuresSchema = mongoose.Schema({
 });
 
 // compile schema to model
-var User = mongoose.model('Users', usersSchema);
-var structuresType = mongoose.model('structureType', structuresTypeSchema);
-var categoriesOthers = mongoose.model('categoriesOthers', categoriesOthersSchema);
-var categoriesAccompanements = mongoose.model('CategoriesAccompagnement', categoriesAccompanementsSchema);
-var categoriesFormation = mongoose.model('categoriesFormation', categoriesFormationSchema);
-var structures = mongoose.model('structures', structuresSchema);
+const user = mongoose.model('users', usersSchema);
+const structuresType = mongoose.model('structureType', structuresTypeSchema);
+const categoriesOthers = mongoose.model('categoriesOthers', categoriesOthersSchema);
+const categoriesAccompanements = mongoose.model('CategoriesAccompagnement', categoriesAccompanementsSchema);
+const categoriesFormation = mongoose.model('categoriesFormation', categoriesFormationSchema);
+const structures = mongoose.model('structures', structuresSchema);
+const jobs = mongoose.model('jobs', jobsSchema);
+const employers = mongoose.model('employers', employersSchema);
 
 /* drop users collections */
 mongoose.connection.dropCollection('users', async (err) => {
@@ -140,7 +166,7 @@ mongoose.connection.dropCollection('users', async (err) => {
     user.password = hashPassword();
   });
   // save model to database
-  User.create(userData.data, function (error, user) {
+  user.create(userData.data, (error) => {
     if (error) return console.error(error);
     console.log('-- Users collection initialized --');
   });
@@ -180,6 +206,20 @@ mongoose.connection.dropCollection('structures', async (err) => {
   await handleError('structures', err);
   structures.create(structuresData.data, (error) => {
     if (error) return console.error(error);
+  });
+});
+/* Create structures */
+mongoose.connection.dropCollection('jobs', async (err) => {
+  await handleError('jobs', err);
+  jobs.create(jobsData.data, (error) => {
+    if (error) return console.error(error);
+  });
+});
+/* Create structures */
+mongoose.connection.dropCollection('employers', async (err) => {
+  await handleError('employers', err);
+  employers.create(employersData.data, (error) => {
+    if (error) return console.error(error);
     process.exit(0);
   });
 });
diff --git a/src/auth/auth.controller.spec.ts b/src/auth/auth.controller.spec.ts
index 95c9ef730d15cbedc989a24e41e9618795c86053..8fccb88aae347fbacbe9a58e587e33013ac4e158 100644
--- a/src/auth/auth.controller.spec.ts
+++ b/src/auth/auth.controller.spec.ts
@@ -6,6 +6,7 @@ import { AuthServiceMock } from '../../test/mock/services/auth.mock.service';
 import { ConfigurationModule } from '../configuration/configuration.module';
 import { MailerModule } from '../mailer/mailer.module';
 import { User } from '../users/schemas/user.schema';
+import { UserRegistrySearchService } from '../users/services/userRegistry-search.service';
 import { UsersService } from '../users/services/users.service';
 import { AuthController } from './auth.controller';
 import { AuthService } from './auth.service';
@@ -29,6 +30,10 @@ describe('AuthController', () => {
       providers: [
         AuthService,
         UsersService,
+        {
+          provide: UserRegistrySearchService,
+          useClass: jest.fn(),
+        },
         {
           provide: AuthService,
           useClass: AuthServiceMock,
diff --git a/src/users/controllers/userRegistry.controller.spec.ts b/src/users/controllers/userRegistry.controller.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1cbfb3d63e9e376ac30804a647a558b406dcd001
--- /dev/null
+++ b/src/users/controllers/userRegistry.controller.spec.ts
@@ -0,0 +1,125 @@
+import { getModelToken } from '@nestjs/mongoose';
+import { Test, TestingModule } from '@nestjs/testing';
+import { mulitpleUsers, mulitpleUsersES } from '../../../test/mock/data/users.mock.data';
+import { mockJwtAuthGuard } from '../../../test/mock/guards/jwt-auth.mock.guard';
+import { mockRoleGuard } from '../../../test/mock/guards/role.mock.guard';
+import { JwtAuthGuard } from '../../auth/guards/jwt-auth.guard';
+import { ConfigurationModule } from '../../configuration/configuration.module';
+import { RolesGuard } from '../guards/roles.guard';
+import { User } from '../schemas/user.schema';
+import { UserRegistryService } from '../services/userRegistry.service';
+import { UsersRegistryController } from './userRegistry.controller';
+
+describe('UserRegistryController', () => {
+  let controller: UsersRegistryController;
+
+  const userRegistryServiceMock = {
+    findAllForIndexation: jest.fn(),
+    countAllUserRegistry: jest.fn(),
+    findAllUserRegistry: jest.fn(),
+    findUsersByNameEmployerOrJob: jest.fn(),
+    searchByNameAndSurname: jest.fn(),
+    initUserRegistryIndex: jest.fn(),
+    populateES: jest.fn(),
+  };
+
+  beforeEach(async () => {
+    const module: TestingModule = await Test.createTestingModule({
+      imports: [ConfigurationModule],
+      providers: [
+        {
+          provide: UserRegistryService,
+          useValue: userRegistryServiceMock,
+        },
+        {
+          provide: getModelToken('User'),
+          useValue: User,
+        },
+      ],
+      controllers: [UsersRegistryController],
+    })
+      .overrideGuard(JwtAuthGuard)
+      .useValue(mockJwtAuthGuard)
+      .overrideGuard(RolesGuard)
+      .useValue(mockRoleGuard)
+      .compile();
+
+    controller = module.get<UsersRegistryController>(UsersRegistryController);
+  });
+
+  it('should be defined', () => {
+    expect(controller).toBeDefined();
+  });
+
+  describe('findAll', () => {
+    it('should findAll with searchTerm, job and employer', async () => {
+      userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]);
+      const reply = await controller.findAll({ search: 'adm' }, { page: 1, job: ['CNFS'], employer: ['Pimms'] });
+      expect(reply).toStrictEqual([mulitpleUsers[0]]);
+    });
+    it('should findAll with searchTerm, empty job and empty employer', async () => {
+      userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]);
+      const reply = await controller.findAll({ search: 'adm' }, { page: 1, job: [], employer: [] });
+      expect(reply).toStrictEqual([mulitpleUsers[0]]);
+    });
+    it('should findAll with searchTerm and no filter arrays', async () => {
+      userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]);
+      const reply = await controller.findAll({ search: 'adm' }, { page: 1 });
+      expect(reply).toStrictEqual([mulitpleUsers[0]]);
+    });
+    it('should findAll with searchTerm and empty job', async () => {
+      userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]);
+      const reply = await controller.findAll({ search: 'adm' }, { page: 1, job: [] });
+      expect(reply).toStrictEqual([mulitpleUsers[0]]);
+    });
+    it('should findAll with searchTerm and empty employer', async () => {
+      userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]);
+      const reply = await controller.findAll({ search: 'adm' }, { page: 1, employer: [] });
+      expect(reply).toStrictEqual([mulitpleUsers[0]]);
+    });
+    it('should findAll with no searchTerm and employer filter', async () => {
+      userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]);
+      const reply = await controller.findAll({ search: '' }, { page: 1, employer: ['CAF'] });
+      expect(reply).toStrictEqual([mulitpleUsers[0]]);
+    });
+    it('should findAll with no searchTerm and job filter', async () => {
+      userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]);
+      const reply = await controller.findAll({ search: '' }, { page: 1, job: ['CNFS'] });
+      expect(reply).toStrictEqual([mulitpleUsers[0]]);
+    });
+    it('should findAll with no searchTerm and filters', async () => {
+      userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]);
+      const reply = await controller.findAll({ search: '' }, { page: 1, job: ['CNFS'], employer: ['CAF'] });
+      expect(reply).toStrictEqual([mulitpleUsers[0]]);
+    });
+    it('should findAll with searchTerm and undefined filters', async () => {
+      userRegistryServiceMock.findUsersByNameEmployerOrJob.mockResolvedValue([mulitpleUsers[0]]);
+      const reply = await controller.findAll({ search: 'adm' });
+      expect(reply).toStrictEqual([mulitpleUsers[0]]);
+    });
+    it('should findAll with no searchTerm and no filter arrays', async () => {
+      userRegistryServiceMock.findAllUserRegistry.mockResolvedValue(mulitpleUsers);
+      const reply = await controller.findAll({ search: '' }, { page: 1 });
+      expect(reply).toBe(mulitpleUsers);
+    });
+    it('should findAll with empty search end undefined filters', async () => {
+      userRegistryServiceMock.findAllUserRegistry.mockResolvedValue(mulitpleUsers);
+      const reply = await controller.findAll({ search: '' });
+      expect(reply).toBe(mulitpleUsers);
+    });
+  });
+  describe('findAllCount', () => {
+    it('should findAllCount', async () => {
+      userRegistryServiceMock.countAllUserRegistry.mockResolvedValue(10);
+      const reply = await controller.findAllCount();
+      expect(reply).toStrictEqual(10);
+    });
+  });
+  describe('resetES', () => {
+    it('should reset elastic search indexes', async () => {
+      userRegistryServiceMock.initUserRegistryIndex.mockResolvedValue(mulitpleUsersES);
+      const reply = await controller.resetES();
+      expect(reply).toStrictEqual(mulitpleUsersES);
+    });
+  });
+});
diff --git a/src/users/controllers/userRegistry.controller.ts b/src/users/controllers/userRegistry.controller.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e4cbb8da3a340927060fc7de8e94f1d87fce90bb
--- /dev/null
+++ b/src/users/controllers/userRegistry.controller.ts
@@ -0,0 +1,60 @@
+import { Body, Controller, Get, Logger, Post, Query, UseGuards } from '@nestjs/common';
+import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
+import { JwtAuthGuard } from '../../auth/guards/jwt-auth.guard';
+import { Roles } from '../decorators/roles.decorator';
+import { RolesGuard } from '../guards/roles.guard';
+import { IUserRegistry, UserRegistryPaginatedResponse } from '../interfaces/userRegistry.interface';
+import { UserRegistryService } from '../services/userRegistry.service';
+
+@ApiTags('userRegistry')
+@Controller('userRegistry')
+export class UsersRegistryController {
+  private readonly logger = new Logger(UsersRegistryController.name);
+  constructor(private userRegistryService: UserRegistryService) {}
+
+  /**
+   * Find all users in Registry. If search is given as param, filter on it. Otherwise return everything. Results comes paginated (default is 20 per page, defined in service)
+   * @param query {Query}
+   * @returns {PaginatedResponse}
+   */
+  @UseGuards(JwtAuthGuard)
+  @ApiBearerAuth('JWT')
+  @Post()
+  public async findAll(
+    @Query() query?: { search: string },
+    @Body() filters?: { job?: string[]; employer?: string[]; page: number }
+  ): Promise<UserRegistryPaginatedResponse> {
+    if (query.search || filters?.job?.length || filters?.employer?.length) {
+      this.logger.debug(`findAll with query ${query.search}`);
+      return this.userRegistryService.findUsersByNameEmployerOrJob(
+        query.search || '',
+        filters?.page || 1,
+        filters?.job || [],
+        filters?.employer || []
+      );
+    }
+    this.logger.debug('findAll without query');
+    return this.userRegistryService.findAllUserRegistry(filters?.page || 1);
+  }
+
+  /**
+   * Return every user in registry
+   * @returns {Promise<number>}
+   */
+  @Get('/count')
+  public async findAllCount(): Promise<number> {
+    this.logger.debug('findAll UserRegistry');
+    return this.userRegistryService.countAllUserRegistry();
+  }
+
+  /**
+   * Init or reset search index for users
+   * @returns {IUserRegistry[]}
+   */
+  @Post('searchIndex')
+  @UseGuards(JwtAuthGuard, RolesGuard)
+  @Roles('admin')
+  public async resetES(): Promise<IUserRegistry[]> {
+    return this.userRegistryService.initUserRegistryIndex();
+  }
+}
diff --git a/src/users/interfaces/userRegistry-search-body.interface.ts b/src/users/interfaces/userRegistry-search-body.interface.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e2e07925ec6ec143aef9e5541b9cdc7a3a294335
--- /dev/null
+++ b/src/users/interfaces/userRegistry-search-body.interface.ts
@@ -0,0 +1,10 @@
+import { Employer } from '../schemas/employer.schema';
+import { Job } from '../schemas/job.schema';
+
+export interface UserRegistrySearchBody {
+  id: string;
+  name: string;
+  surname: string;
+  job: Job;
+  employer: Employer;
+}
diff --git a/src/users/interfaces/userRegistry-search-response.interface.ts b/src/users/interfaces/userRegistry-search-response.interface.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1359d0bc1d97892f418e1074464c08bbfd5266c4
--- /dev/null
+++ b/src/users/interfaces/userRegistry-search-response.interface.ts
@@ -0,0 +1,12 @@
+import { UserRegistrySearchBody } from './userRegistry-search-body.interface';
+
+export interface UserRegistrySearchResult {
+  hits: {
+    total: number;
+    max_score: number;
+    hits: Array<{
+      _score: number;
+      _source: UserRegistrySearchBody;
+    }>;
+  };
+}
diff --git a/src/users/interfaces/userRegistry.interface.ts b/src/users/interfaces/userRegistry.interface.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b4843544ecfce5ba07c33a7085f9c2ee1f2d4a42
--- /dev/null
+++ b/src/users/interfaces/userRegistry.interface.ts
@@ -0,0 +1,23 @@
+import { IUser } from './user.interface';
+
+export type IUserRegistry = Omit<
+  IUser,
+  | 'email'
+  | 'phone'
+  | 'password'
+  | 'emailVerified'
+  | 'validationToken'
+  | 'resetPasswordToken'
+  | 'role'
+  | 'changeEmailToken'
+  | 'newEmail'
+  | 'structuresLink'
+  | 'pendingStructuresLink'
+  | 'structureOutdatedMailSent'
+  | 'personalOffers'
+  | 'description'
+>;
+export interface UserRegistryPaginatedResponse {
+  count: number;
+  docs: IUserRegistry[];
+}
diff --git a/src/users/schemas/user.schema.ts b/src/users/schemas/user.schema.ts
index 20123c65d0fb507671c751507222a547539e729d..3c1b9da92e756f6b7edb3ecb2b29925d8b35799a 100644
--- a/src/users/schemas/user.schema.ts
+++ b/src/users/schemas/user.schema.ts
@@ -66,3 +66,4 @@ export class User {
 }
 
 export const UserSchema = SchemaFactory.createForClass(User);
+UserSchema.index({ name: 'text', surname: 'text' });
diff --git a/src/users/services/userRegistry-search.service.spec.ts b/src/users/services/userRegistry-search.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b790a65f28ef5530ef6ddc35d6f81dd21d3de7c0
--- /dev/null
+++ b/src/users/services/userRegistry-search.service.spec.ts
@@ -0,0 +1,64 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { mulitpleUsers, mulitpleUsersES } from '../../../test/mock/data/users.mock.data';
+import { ConfigurationModule } from '../../configuration/configuration.module';
+import { SearchModule } from '../../search/search.module';
+import { IUserRegistry } from '../interfaces/userRegistry.interface';
+import { UserRegistrySearchService } from './userRegistry-search.service';
+
+describe('UserRegistrySearchService Search cases', () => {
+  let service: UserRegistrySearchService;
+
+  beforeEach(async () => {
+    const module: TestingModule = await Test.createTestingModule({
+      imports: [SearchModule, ConfigurationModule],
+      providers: [UserRegistrySearchService],
+    }).compile();
+
+    service = module.get<UserRegistrySearchService>(UserRegistrySearchService);
+    service['index'] = 'user-unit-test';
+    // Init test cases
+    await service.dropIndex();
+    await service.createUserRegistryIndex();
+    await Promise.all(mulitpleUsersES.map((user: any) => service.indexUserRegistry(user)));
+
+    // wait for the new structures to be indexed before search
+    await service.refreshIndexUserRegistry();
+    await new Promise((r) => setTimeout(r, 2000));
+  }, 10000);
+
+  it('should be defined', async () => {
+    expect(service).toBeDefined();
+  });
+  describe('Search method', () => {
+    it('should find Guilhem', async () => {
+      const res = await service.search('Guilhem');
+      expect(res[0].surname).toBe('Guilhem');
+      expect(res.length).toBe(1);
+    });
+    it('should find adm', async () => {
+      const res = await service.search('adm');
+      expect(res[0].name).toBe('Admin');
+      expect(res.length).toBe(1);
+    });
+    it('should find empty string', async () => {
+      const res = await service.search('');
+      expect(res.length).toBe(6);
+    });
+  });
+  describe('Indexation methods', () => {
+    it('should index User', async () => {
+      const res = await Promise.all(mulitpleUsersES.map((user: any) => service.indexUserRegistry(user)));
+      expect(res).toBeTruthy();
+      expect(res.length).toBe(6);
+    });
+    it('should update index', async () => {
+      const res = await service.update(mulitpleUsers[0] as IUserRegistry);
+      expect(res).toBeTruthy();
+    });
+    it('should delete index', async () => {
+      const resAdm = await service.search('adm');
+      const res = await service.deleteIndex(resAdm[0] as IUserRegistry);
+      expect(res).toBeTruthy();
+    });
+  });
+});
diff --git a/src/users/services/userRegistry-search.service.ts b/src/users/services/userRegistry-search.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..43dd4cb63808bd31481bb131fb76911f81f0178a
--- /dev/null
+++ b/src/users/services/userRegistry-search.service.ts
@@ -0,0 +1,120 @@
+import { Injectable, Logger } from '@nestjs/common';
+import { ElasticsearchService } from '@nestjs/elasticsearch';
+import { UserRegistrySearchBody } from '../interfaces/userRegistry-search-body.interface';
+import { UserRegistrySearchResult } from '../interfaces/userRegistry-search-response.interface';
+import { IUserRegistry } from '../interfaces/userRegistry.interface';
+
+@Injectable()
+export class UserRegistrySearchService {
+  private index = 'user';
+  private readonly logger = new Logger(UserRegistrySearchService.name);
+
+  constructor(private readonly elasticsearchService: ElasticsearchService) {}
+
+  public async indexUserRegistry(user: IUserRegistry): Promise<IUserRegistry> {
+    this.logger.debug(`indexUser ${user.name} ${user.surname}`);
+    this.elasticsearchService.index<UserRegistrySearchResult, UserRegistrySearchBody>({
+      index: this.index,
+      id: user.id,
+      body: {
+        name: user.name,
+        id: user.id,
+        surname: user.surname,
+        job: user.job,
+        employer: user.employer,
+      },
+    });
+    return user;
+  }
+
+  public async createUserRegistryIndex(): Promise<any> {
+    this.logger.debug('createUserRegistryIndex');
+    return this.elasticsearchService.indices.create({
+      index: this.index,
+      body: {
+        settings: {
+          analysis: {
+            analyzer: {
+              default: {
+                type: 'french',
+              },
+              default_search: {
+                type: 'french',
+              },
+            },
+          },
+        },
+      },
+    });
+  }
+
+  public async dropIndex(): Promise<any> {
+    this.logger.debug('dropIndex');
+    const foundIndexes = (
+      await this.elasticsearchService.indices.exists({
+        index: this.index,
+      })
+    ).body;
+    if (foundIndexes) {
+      return this.elasticsearchService.indices.delete({
+        index: this.index,
+      });
+    }
+  }
+
+  public async deleteIndex(user: IUserRegistry): Promise<IUserRegistry> {
+    this.logger.debug('deleteIndex');
+    this.elasticsearchService.delete<UserRegistrySearchResult, IUserRegistry>({
+      index: this.index,
+      id: user._id,
+    });
+    return user;
+  }
+
+  public async refreshIndexUserRegistry(): Promise<any> {
+    this.logger.debug('refreshIndexUserRegistry');
+    return this.elasticsearchService.indices.refresh({
+      index: this.index,
+    });
+  }
+
+  public async search(searchString: string): Promise<any[]> {
+    this.logger.debug(`search user with query: ${searchString}`);
+    searchString = searchString ? '*' + searchString + '*' : '*';
+    const { body } = await this.elasticsearchService.search<UserRegistrySearchResult>({
+      index: this.index,
+      body: {
+        from: 0,
+        size: 200,
+        query: {
+          query_string: {
+            analyze_wildcard: 'true',
+            query: searchString,
+            fields: ['name', 'surname'],
+            fuzziness: 'AUTO',
+          },
+        },
+      },
+    });
+    const sortedHits = body.hits.hits.filter(function (elem) {
+      return elem._score >= body.hits.max_score;
+    });
+    return sortedHits.map((item) => item._source);
+  }
+
+  public async update(user: IUserRegistry): Promise<any> {
+    this.logger.debug(`Updates user : ${user._id} `);
+    return this.elasticsearchService.update({
+      index: this.index,
+      id: user._id,
+      body: {
+        doc: {
+          name: user.name,
+          surname: user.surname,
+          job: user.job,
+          employer: user.employer,
+        },
+      },
+    });
+  }
+}
diff --git a/src/users/services/userRegistry.service.spec.ts b/src/users/services/userRegistry.service.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0df3a840e63bbdc962004ba3b2c557a5b2361d64
--- /dev/null
+++ b/src/users/services/userRegistry.service.spec.ts
@@ -0,0 +1,241 @@
+import { HttpModule } from '@nestjs/axios';
+import { getModelToken } from '@nestjs/mongoose';
+import { Test, TestingModule } from '@nestjs/testing';
+import { Types } from 'mongoose';
+import { mulitpleUsers, mulitpleUsersES } from '../../../test/mock/data/users.mock.data';
+import { ConfigurationModule } from '../../configuration/configuration.module';
+import { IUserRegistry } from '../interfaces/userRegistry.interface';
+import { EmployerService } from './employer.service';
+import { JobsService } from './jobs.service';
+import { UserRegistrySearchService } from './userRegistry-search.service';
+import { UserRegistryService } from './userRegistry.service';
+
+describe('userRegistryService', () => {
+  let service: UserRegistryService;
+  const mockUserRegistryModel = {
+    find: jest.fn(() => mockUserRegistryModel),
+    populate: jest.fn(() => mockUserRegistryModel),
+    sort: jest.fn(() => mockUserRegistryModel),
+    select: jest.fn(() => mockUserRegistryModel),
+    exec: jest.fn(() => mockUserRegistryModel),
+    count: jest.fn(() => mockUserRegistryModel),
+    limit: jest.fn(() => mockUserRegistryModel),
+  };
+
+  const mockUserRegistrySearchService = {
+    search: jest.fn(),
+    dropIndex: jest.fn(),
+    deleteIndex: jest.fn(),
+    createUserRegistryIndex: jest.fn(),
+    indexUserRegistry: jest.fn(),
+  };
+  const mockEmployersService = {
+    findByName: jest.fn(),
+  };
+  const mockJobsService = {
+    findByName: jest.fn(),
+  };
+
+  beforeEach(async () => {
+    const module: TestingModule = await Test.createTestingModule({
+      imports: [ConfigurationModule, HttpModule],
+      providers: [
+        UserRegistryService,
+        {
+          provide: UserRegistrySearchService,
+          useValue: mockUserRegistrySearchService,
+        },
+        {
+          provide: getModelToken('User'),
+          useValue: mockUserRegistryModel,
+        },
+        {
+          provide: JobsService,
+          useValue: mockJobsService,
+        },
+        {
+          provide: EmployerService,
+          useValue: mockEmployersService,
+        },
+      ],
+    }).compile();
+    service = module.get<UserRegistryService>(UserRegistryService);
+  });
+
+  it('should be defined', () => {
+    expect(service).toBeDefined();
+  });
+
+  describe('findAll', () => {
+    const result: IUserRegistry[] = [
+      {
+        _id: Types.ObjectId('6319dfa79672971e1f8fe1b7'),
+        surname: 'ADMIN',
+        name: 'Admin',
+        employer: {
+          name: 'Pimms',
+          validated: true,
+        },
+        job: {
+          hasPersonalOffer: true,
+
+          name: 'CNFS',
+          validated: true,
+        },
+      },
+    ] as IUserRegistry[];
+    it('should findAll UserRegistry for indexation', async () => {
+      mockUserRegistryModel.exec.mockResolvedValueOnce(result);
+      expect(await service.findAllForIndexation()).toBe(result);
+    });
+
+    it('should findAll UserRegistry count', async () => {
+      mockUserRegistryModel.exec.mockResolvedValueOnce(result.length);
+      expect(await service.countAllUserRegistry()).toBe(result.length);
+    });
+    it('should findAllUserRegistry with page number 1', async () => {
+      const res = { count: 1, docs: result };
+      mockUserRegistryModel.exec.mockResolvedValueOnce(1);
+      mockUserRegistryModel.exec.mockResolvedValueOnce(result);
+      expect(await service.findAllUserRegistry(1)).toStrictEqual(res);
+    });
+  });
+  describe('find with filter', () => {
+    const result: IUserRegistry[] = [
+      {
+        _id: Types.ObjectId('6319dfa79672971e1f8fe1b7'),
+        surname: 'ADMIN',
+        name: 'Admin',
+        employer: {
+          name: 'Pimms',
+          validated: true,
+        },
+        job: {
+          hasPersonalOffer: true,
+
+          name: 'CNFS',
+          validated: true,
+        },
+      },
+    ] as IUserRegistry[];
+    const res = {
+      count: 1,
+      docs: [
+        {
+          _id: Types.ObjectId('6319dfa79672971e1f8fe1b7'),
+          surname: 'ADMIN',
+          name: 'Admin',
+          employer: {
+            name: 'Pimms',
+            validated: true,
+          },
+          job: {
+            hasPersonalOffer: true,
+
+            name: 'CNFS',
+            validated: true,
+          },
+        },
+      ],
+    };
+    it('should findUsersByNameEmployerOrJob with string param and get a result', async () => {
+      mockUserRegistrySearchService.search.mockResolvedValueOnce(result);
+      expect(await service.findUsersByNameEmployerOrJob('adm', 1)).toStrictEqual(res);
+    });
+    it('should findUsersByNameEmployerOrJob with string param and get no result', async () => {
+      const emptyRes = { count: 0, docs: [] };
+      mockUserRegistrySearchService.search.mockResolvedValueOnce([]);
+      expect(await service.findUsersByNameEmployerOrJob('azerty', 1)).toStrictEqual(emptyRes);
+    });
+    it('should findUsersByNameEmployerOrJob with no string param and filters', async () => {
+      const res = { count: 1, docs: [mulitpleUsersES[1]] };
+      const jobList = [
+        {
+          hasPersonalOffer: true,
+          name: 'CNFS',
+          validated: true,
+        },
+      ];
+      const employerList = [{ name: 'Métropole', validated: true }];
+      mockUserRegistrySearchService.search.mockResolvedValueOnce(mulitpleUsersES);
+      mockJobsService.findByName.mockResolvedValueOnce(jobList[0]);
+      mockEmployersService.findByName.mockResolvedValueOnce(employerList[0]);
+      mockUserRegistryModel.exec.mockResolvedValueOnce(mulitpleUsers);
+      expect(await service.findUsersByNameEmployerOrJob('', 1, ['CNFS'], ['Métropole'])).toStrictEqual(res);
+    });
+
+    it('should findUsersByNameEmployerOrJob with string param and filters', async () => {
+      const res = { count: 1, docs: [mulitpleUsersES[1]] };
+      const jobList = [
+        {
+          hasPersonalOffer: true,
+          name: 'CNFS',
+          validated: true,
+        },
+      ];
+      const employerList = [{ name: 'Métropole', validated: true }];
+      mockUserRegistrySearchService.search.mockResolvedValueOnce([mulitpleUsersES[1]]);
+      mockJobsService.findByName.mockResolvedValueOnce(jobList[0]);
+      mockEmployersService.findByName.mockResolvedValueOnce(employerList[0]);
+      mockUserRegistryModel.exec.mockResolvedValueOnce(mulitpleUsers);
+      expect(await service.findUsersByNameEmployerOrJob('Guil', 1, ['CNFS'], ['Métropole'])).toStrictEqual(res);
+    });
+    it('should findUsersByNameEmployerOrJob with string param and filters and return empty', async () => {
+      const res = { count: 0, docs: [] };
+      const jobList = [
+        {
+          hasPersonalOffer: true,
+          name: 'CNFS',
+          validated: true,
+        },
+      ];
+      const employerList = [{ name: 'Métropole', validated: true }];
+      mockUserRegistrySearchService.search.mockResolvedValueOnce([]);
+      mockJobsService.findByName.mockResolvedValueOnce(jobList[0]);
+      mockEmployersService.findByName.mockResolvedValueOnce(employerList[0]);
+      mockUserRegistryModel.exec.mockResolvedValueOnce([]);
+      expect(await service.findUsersByNameEmployerOrJob('azerrttt', 1, ['CNFS'], ['Métropole'])).toStrictEqual(res);
+    });
+    it('should findUsersByNameEmployerOrJob with string param and one filter', async () => {
+      const res = { count: 2, docs: [mulitpleUsersES[0], mulitpleUsersES[2]] };
+      const employerList = [{ name: 'CAF', validated: true }];
+      mockUserRegistrySearchService.search.mockResolvedValueOnce(mulitpleUsersES);
+      mockEmployersService.findByName.mockResolvedValueOnce(employerList[0]);
+      mockUserRegistryModel.exec.mockResolvedValueOnce(mulitpleUsers);
+      expect(await service.findUsersByNameEmployerOrJob('a', 1, [], ['CAF'])).toStrictEqual(res);
+    });
+
+    it('should findUsersByNameEmployerOrJob with no string param and one employer filter', async () => {
+      const res = { count: 2, docs: [mulitpleUsersES[2], mulitpleUsersES[3]] };
+
+      const jobList = [
+        {
+          hasPersonalOffer: true,
+          name: 'Conseiller',
+          validated: true,
+        },
+      ];
+      mockUserRegistrySearchService.search.mockResolvedValueOnce(mulitpleUsersES);
+
+      mockJobsService.findByName.mockResolvedValueOnce(jobList[0]);
+      mockUserRegistryModel.exec.mockResolvedValueOnce(mulitpleUsers);
+      expect(await service.findUsersByNameEmployerOrJob('', 1, ['Conseiller'], [])).toStrictEqual(res);
+    });
+  });
+
+  describe('Search', () => {
+    it('should initUserRegistryIndex', async () => {
+      mockUserRegistryModel.exec.mockResolvedValueOnce(mulitpleUsers);
+      mockUserRegistrySearchService.dropIndex.mockResolvedValueOnce({});
+      mockUserRegistrySearchService.createUserRegistryIndex.mockResolvedValueOnce({});
+      mockUserRegistrySearchService.indexUserRegistry.mockResolvedValueOnce({});
+      expect(await service.initUserRegistryIndex()).toBe(mulitpleUsers);
+    });
+
+    it('should findAllUserRegistry with page number 1', async () => {
+      mockUserRegistrySearchService.search.mockResolvedValueOnce([mulitpleUsers[0]]);
+
+      expect(await service.searchByNameAndSurname('adm')).toStrictEqual([mulitpleUsers[0]]);
+    });
+  });
+});
diff --git a/src/users/services/userRegistry.service.ts b/src/users/services/userRegistry.service.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1a7f687b5404405f9107d4b60fc6a901b1e085a2
--- /dev/null
+++ b/src/users/services/userRegistry.service.ts
@@ -0,0 +1,147 @@
+import { Injectable, Logger } from '@nestjs/common';
+import { InjectModel } from '@nestjs/mongoose';
+import { Model } from 'mongoose';
+import { IUser } from '../interfaces/user.interface';
+import { IUserRegistry, UserRegistryPaginatedResponse } from '../interfaces/userRegistry.interface';
+import { Employer } from '../schemas/employer.schema';
+import { Job } from '../schemas/job.schema';
+import { User } from '../schemas/user.schema';
+import { EmployerService } from './employer.service';
+import { JobsService } from './jobs.service';
+import { UserRegistrySearchService } from './userRegistry-search.service';
+
+@Injectable()
+export class UserRegistryService {
+  private readonly logger = new Logger(UserRegistryService.name);
+  constructor(
+    @InjectModel(User.name) private userModel: Model<IUser>,
+    private userRegistrySearchService: UserRegistrySearchService,
+    private jobsService: JobsService,
+    private employerService: EmployerService
+  ) {}
+  public maxPerPage = 20;
+
+  public async findAllForIndexation(): Promise<IUserRegistry[]> {
+    return this.userModel
+      .find()
+      .select('name surname _id job employer ')
+      .populate('job employer')
+      .sort({ surname: 1 })
+      .exec();
+  }
+
+  public async countAllUserRegistry(): Promise<number> {
+    return this.userModel
+      .find()
+      .populate('employer')
+      .populate('job')
+      .select('name surname employer job _id ')
+      .sort({ surname: 1 })
+      .count()
+      .exec();
+  }
+
+  public async findAllUserRegistry(page: number): Promise<UserRegistryPaginatedResponse> {
+    const limit = this.maxPerPage * page;
+    const count = await this.countAllUserRegistry();
+    const docs = await this.userModel
+      .find()
+      .populate('employer')
+      .populate('job')
+      .select('name surname employer job _id ')
+      .limit(limit)
+      .sort({ surname: 1 })
+      .exec();
+    return { count: count, docs: docs };
+  }
+
+  private callbackFilter(users: IUser[], employersList: Employer[], jobList: Job[]): IUser[] {
+    const jobNames: string[] = jobList.map((job) => job.name);
+    const employersNames: string[] = employersList.map((e) => e.name);
+    // For each filter list (job or employer), we'll filter the main user list in order to get only the user that have a job or employer contained in the filters array
+    // For this, we une findexIndex method on job/employer name
+    if (employersList?.length && jobList?.length) {
+      return users.filter(
+        (user) =>
+          jobNames.findIndex((n) => user.job.name === n) > -1 &&
+          employersNames.findIndex((n) => user.employer.name === n) > -1
+      );
+    }
+
+    if (employersList?.length) {
+      return users.filter((user) => employersNames.findIndex((n) => user.employer.name === n) > -1);
+    }
+    if (jobList?.length) {
+      return users.filter((user) => jobNames.findIndex((n) => user.job.name === n) > -1);
+    }
+  }
+
+  public async findUsersByNameEmployerOrJob(
+    searchParam: string,
+    page: number,
+    jobs?: string[],
+    employers?: string[]
+  ): Promise<UserRegistryPaginatedResponse> {
+    const results = await this.userRegistrySearchService.search(searchParam);
+    const limit = page * this.maxPerPage || this.maxPerPage;
+    if (jobs?.length || employers?.length) {
+      const jobList: Job[] = [];
+      const employersList: Employer[] = [];
+      if (jobs) {
+        for (const job of jobs) {
+          jobList.push(await this.jobsService.findByName(job));
+        }
+      }
+      if (employers) {
+        for (const employer of employers) {
+          employersList.push(await this.employerService.findByName(employer));
+        }
+      }
+      const resultsWithFilter = await this.userModel
+        .find({
+          $or: [
+            {
+              job: { $exists: true },
+            },
+            {
+              employer: { $exists: true },
+            },
+          ],
+        })
+        .select('name surname employer job _id ')
+        .populate('employer job')
+        .sort({ surname: 1 })
+        .exec()
+        .then((res) => {
+          return this.callbackFilter(res, employersList, jobList);
+        });
+      const idsWithFilter = resultsWithFilter.map((user) => user._id.toString());
+      const mergedResults = results.filter((user) => idsWithFilter.includes(user.id.toString()));
+      return { count: mergedResults.length, docs: mergedResults.splice(0, limit) };
+    }
+    return { count: results.length, docs: results.splice(0, limit) };
+  }
+
+  // SEARCH
+  public async searchByNameAndSurname(searchString: string): Promise<any[]> {
+    this.logger.debug('searchByNameAndSurname');
+    return this.userRegistrySearchService.search(searchString);
+  }
+
+  public async initUserRegistryIndex(): Promise<IUserRegistry[]> {
+    Logger.log('Reset structures indexes');
+    await this.userRegistrySearchService.dropIndex();
+    await this.userRegistrySearchService.createUserRegistryIndex();
+    return this.populateES();
+  }
+
+  private async populateES(): Promise<IUserRegistry[]> {
+    const users = await this.findAllForIndexation();
+    await Promise.all(
+      users.map((user: IUserRegistry) => {
+        this.userRegistrySearchService.indexUserRegistry(user);
+      })
+    );
+    return users;
+  }
+}
diff --git a/src/users/services/users.service.spec.ts b/src/users/services/users.service.spec.ts
index e9257eed319cbdd59b0a928d923cb0125d38140c..f88eeddc58c652836999571e1e7ac7aa02e3994a 100644
--- a/src/users/services/users.service.spec.ts
+++ b/src/users/services/users.service.spec.ts
@@ -17,6 +17,7 @@ import { User } from '../schemas/user.schema';
 import { IUser } from '../interfaces/user.interface';
 import { UpdateDetailsDto } from '../dto/update-details.dto';
 import { DescriptionDto } from '../dto/description.dto';
+import { UserRegistrySearchService } from './userRegistry-search.service';
 
 function hashPassword() {
   return bcrypt.hashSync(process.env.USER_PWD, process.env.SALT);
@@ -24,14 +25,26 @@ function hashPassword() {
 
 const mockUserModel = {
   create: jest.fn(),
-  findOne: jest.fn(),
+  findOne: jest.fn(() => mockUserModel),
   findById: jest.fn(),
   deleteOne: jest.fn(),
   updateMany: jest.fn(),
   exec: jest.fn(),
   find: jest.fn(() => mockUserModel),
   sort: jest.fn(() => mockUserModel),
-  findByIdAndUpdate: jest.fn(),
+  populate: jest.fn(() => mockUserModel),
+  select: jest.fn(() => mockUserModel),
+  limit: jest.fn(() => mockUserModel),
+  findByIdAndUpdate: jest.fn(() => mockUserModel),
+  findPopulatedUserRegistryById: jest.fn(() => mockUserModel),
+};
+const mockUserRegistrySearchService = {
+  indexUserRegistry: jest.fn(),
+  search: jest.fn(),
+  dropIndex: jest.fn(),
+  createindexUserRegistryIndex: jest.fn(),
+  deleteIndex: jest.fn(),
+  update: jest.fn(),
 };
 
 describe('UsersService', () => {
@@ -42,6 +55,11 @@ describe('UsersService', () => {
       imports: [MailerModule, ConfigurationModule],
       providers: [
         UsersService,
+        UserRegistrySearchService,
+        {
+          provide: UserRegistrySearchService,
+          useValue: mockUserRegistrySearchService,
+        },
         {
           provide: getModelToken('User'),
           useValue: mockUserModel,
@@ -481,6 +499,7 @@ describe('UsersService', () => {
       const user = usersMockData[0];
       const detailsDto: UpdateDetailsDto = { name: 'Michel', surname: 'Chelmi', phone: '0601020304' };
       mockUserModel.findByIdAndUpdate.mockResolvedValueOnce({ ...user, ...detailsDto });
+      mockUserModel.findPopulatedUserRegistryById.mockResolvedValueOnce({ ...user, ...detailsDto });
       const updatedUser = await service.updateUserDetails('', { name: '', surname: '', phone: '' });
       expect(updatedUser.name).toBe(detailsDto.name);
       expect(updatedUser.surname).toBe(detailsDto.surname);
diff --git a/src/users/services/users.service.ts b/src/users/services/users.service.ts
index ce13aedd541dee163004f11f63233a15ccc1cc5d..19c9d58b63c09a3e9eea3cf41f384c44b0b913fa 100644
--- a/src/users/services/users.service.ts
+++ b/src/users/services/users.service.ts
@@ -18,6 +18,8 @@ import { JobDocument } from '../schemas/job.schema';
 import { PersonalOfferDocument } from '../../personal-offers/schemas/personal-offer.schema';
 import { UpdateDetailsDto } from '../dto/update-details.dto';
 import { DescriptionDto } from '../dto/description.dto';
+import { UserRegistrySearchService } from './userRegistry-search.service';
+import { IUserRegistry } from '../interfaces/userRegistry.interface';
 
 @Injectable()
 export class UsersService {
@@ -25,6 +27,7 @@ export class UsersService {
   constructor(
     @InjectModel(User.name) private userModel: Model<IUser>,
     private readonly mailerService: MailerService,
+    private userRegistrySearchService: UserRegistrySearchService,
     private configurationService: ConfigurationService
   ) {}
 
@@ -55,6 +58,7 @@ export class UsersService {
     // Send verification email
     createUser = await this.verifyUserMail(createUser);
     createUser.save();
+    this.userRegistrySearchService.indexUserRegistry(createUser);
     return this.findOne(createUserDto.email);
   }
 
@@ -90,6 +94,15 @@ export class UsersService {
   public findAll(): Promise<User[]> {
     return this.userModel.find().populate('employer').populate('job').select('-password').exec();
   }
+  public async findPopulatedUserRegistryById(userId: string): Promise<IUserRegistry> {
+    return this.userModel
+      .findOne({ _id: userId })
+      .select('name surname _id job employer ')
+      .populate('job employer')
+      .sort({ surname: 1 })
+      .limit(1)
+      .exec();
+  }
 
   public findAllUnattached(): Promise<IUser[]> {
     return this.userModel
@@ -641,6 +654,7 @@ export class UsersService {
     if (!user) {
       throw new HttpException('Invalid user email', HttpStatus.BAD_REQUEST);
     }
+    this.userRegistrySearchService.deleteIndex(user);
     return user.deleteOne();
   }
 
@@ -649,6 +663,7 @@ export class UsersService {
     if (!user) {
       throw new HttpException('Invalid user id', HttpStatus.BAD_REQUEST);
     }
+    this.userRegistrySearchService.deleteIndex(user);
     return user.deleteOne();
   }
 
@@ -697,7 +712,9 @@ export class UsersService {
    */
   public async updateUserProfile(userId: Types.ObjectId, employer: EmployerDocument, job: JobDocument): Promise<any> {
     this.logger.debug(`updateUserProfile | ${userId}`);
-    return this.userModel.updateOne({ _id: userId }, { $set: { employer: employer._id, job: job._id } });
+    const updated = await this.userModel.updateOne({ _id: userId }, { $set: { employer: employer._id, job: job._id } });
+    if (updated) this.userRegistrySearchService.update(updated);
+    return updated;
   }
 
   /**
@@ -707,7 +724,12 @@ export class UsersService {
    */
   public async updateUserJob(userId: Types.ObjectId, job: JobDocument): Promise<any> {
     this.logger.debug(`updateUserProfile - Job | ${userId}`);
-    return this.userModel.updateOne({ _id: userId }, { $set: { job: job._id } });
+    const updated = await this.userModel.updateOne({ _id: userId }, { $set: { job: job._id } });
+    if (updated) {
+      const populatedResult = await this.findPopulatedUserRegistryById(updated._id);
+      this.userRegistrySearchService.update(populatedResult);
+    }
+    return updated;
   }
 
   /**
@@ -717,7 +739,12 @@ export class UsersService {
    */
   public async updateUserEmployer(userId: Types.ObjectId, employer: EmployerDocument): Promise<any> {
     this.logger.debug(`updateUserProfile - Employer | ${userId}`);
-    return this.userModel.updateOne({ _id: userId }, { $set: { employer: employer._id } });
+    const updated = await this.userModel.updateOne({ _id: userId }, { $set: { employer: employer._id } });
+    if (updated) {
+      const populatedResult = await this.findPopulatedUserRegistryById(updated._id);
+      this.userRegistrySearchService.update(populatedResult);
+    }
+    return updated;
   }
 
   /**
@@ -731,6 +758,8 @@ export class UsersService {
     if (!result) {
       throw new HttpException('User not found', HttpStatus.BAD_REQUEST);
     }
+    const populatedResult = await this.findPopulatedUserRegistryById(userId);
+    this.userRegistrySearchService.update(populatedResult);
     return result;
   }
 
@@ -745,6 +774,8 @@ export class UsersService {
     if (!result) {
       throw new HttpException('User not found', HttpStatus.BAD_REQUEST);
     }
+    const populatedResult = await this.findPopulatedUserRegistryById(userId);
+    this.userRegistrySearchService.update(populatedResult);
     return result;
   }
 }
diff --git a/src/users/users.module.ts b/src/users/users.module.ts
index 6d25a2461aded667353ba4bf72b4866e9a5881af..d1e46c0c00ae4f03723f51bb17ef2e25f8d663ce 100644
--- a/src/users/users.module.ts
+++ b/src/users/users.module.ts
@@ -15,6 +15,9 @@ import { Job, JobSchema } from './schemas/job.schema';
 import { Employer, EmployerSchema } from './schemas/employer.schema';
 import { EmployerSearchService } from './services/employer-search.service';
 import { SearchModule } from '../search/search.module';
+import { UsersRegistryController } from './controllers/userRegistry.controller';
+import { UserRegistryService } from './services/userRegistry.service';
+import { UserRegistrySearchService } from './services/userRegistry-search.service';
 
 @Module({
   imports: [
@@ -29,8 +32,15 @@ import { SearchModule } from '../search/search.module';
     TempUserModule,
     SearchModule,
   ],
-  providers: [UsersService, JobsService, EmployerSearchService, EmployerService],
-  exports: [UsersService, JobsService, EmployerService],
-  controllers: [UsersController, JobsController, EmployerController],
+  providers: [
+    UsersService,
+    JobsService,
+    EmployerSearchService,
+    EmployerService,
+    UserRegistryService,
+    UserRegistrySearchService,
+  ],
+  exports: [UsersService, JobsService, EmployerService, UserRegistryService, UserRegistrySearchService],
+  controllers: [UsersController, JobsController, EmployerController, UsersRegistryController],
 })
 export class UsersModule {}
diff --git a/test/mock/data/users.mock.data.ts b/test/mock/data/users.mock.data.ts
index cbc762ac71307dd68daad1e76d8298b295c86b0c..cec7d5cd38cae2c1833ad321331199be45c5e272 100644
--- a/test/mock/data/users.mock.data.ts
+++ b/test/mock/data/users.mock.data.ts
@@ -74,3 +74,190 @@ export const userDetails: IUser[] = [
     },
   },
 ] as IUser[];
+
+export const mulitpleUsers: IUser[] = [
+  {
+    _id: '627b85aea0466f0f132e1599',
+    surname: 'ADMIN',
+    name: 'Admin',
+    email: 'admin@admin.com',
+    employer: {
+      name: 'CAF',
+      validated: true,
+    },
+    job: {
+      hasPersonalOffer: true,
+      name: 'CNFS',
+      validated: true,
+    },
+  },
+  {
+    _id: '627b85aea0466f0f132e1598',
+    surname: 'Guilhem',
+    name: 'CARRON',
+    email: 'admin@admin.com',
+    employer: {
+      name: 'Métropole',
+      validated: true,
+    },
+    job: {
+      hasPersonalOffer: true,
+      name: 'CNFS',
+      validated: true,
+    },
+  },
+  {
+    _id: '627b85aea0466f0f132e1597',
+    surname: 'Jean-Paul',
+    name: 'DESCHAMPS',
+    email: 'admin@admin.com',
+    employer: {
+      name: 'CAF',
+      validated: true,
+    },
+    job: {
+      hasPersonalOffer: true,
+      name: 'Conseiller',
+      validated: true,
+    },
+  },
+  {
+    _id: '627b85aea0466f0f132e1596',
+    surname: 'Paula',
+    name: 'Dubois',
+    email: 'admin@admin.com',
+    employer: {
+      name: 'Pimms',
+      validated: true,
+    },
+    job: {
+      hasPersonalOffer: true,
+      name: 'Conseiller',
+      validated: true,
+    },
+  },
+  {
+    _id: '627b85aea0466f0f132e1595',
+    surname: 'Marine',
+    name: 'Ducal',
+    email: 'admin@admin.com',
+    employer: {
+      name: 'Médiateur',
+      validated: true,
+    },
+    job: {
+      hasPersonalOffer: true,
+      name: 'CNFS',
+      validated: true,
+    },
+  },
+  {
+    _id: '627b85aea0466f0f132e1594',
+    surname: 'Bastien',
+    name: 'Dumont',
+    email: 'admin@admin.com',
+    employer: {
+      name: 'Pimms',
+      validated: true,
+    },
+    job: {
+      hasPersonalOffer: true,
+      name: 'CNFS',
+      validated: true,
+    },
+  },
+] as IUser[];
+
+//Elastic search doesn't support _id
+export const mulitpleUsersES: IUser[] = [
+  {
+    id: '627b85aea0466f0f132e1599',
+    surname: 'ADMIN',
+    name: 'Admin',
+    email: 'admin@admin.com',
+    employer: {
+      name: 'CAF',
+      validated: true,
+    },
+    job: {
+      hasPersonalOffer: true,
+      name: 'CNFS',
+      validated: true,
+    },
+  },
+  {
+    id: '627b85aea0466f0f132e1598',
+    surname: 'Guilhem',
+    name: 'CARRON',
+    email: 'admin@admin.com',
+    employer: {
+      name: 'Métropole',
+      validated: true,
+    },
+    job: {
+      hasPersonalOffer: true,
+      name: 'CNFS',
+      validated: true,
+    },
+  },
+  {
+    id: '627b85aea0466f0f132e1597',
+    surname: 'Jean-Paul',
+    name: 'DESCHAMPS',
+    email: 'admin@admin.com',
+    employer: {
+      name: 'CAF',
+      validated: true,
+    },
+    job: {
+      hasPersonalOffer: true,
+      name: 'Conseiller',
+      validated: true,
+    },
+  },
+  {
+    id: '627b85aea0466f0f132e1596',
+    surname: 'Paula',
+    name: 'Dubois',
+    email: 'admin@admin.com',
+    employer: {
+      name: 'Pimms',
+      validated: true,
+    },
+    job: {
+      hasPersonalOffer: true,
+      name: 'Conseiller',
+      validated: true,
+    },
+  },
+  {
+    id: '627b85aea0466f0f132e1595',
+    surname: 'Marine',
+    name: 'Ducal',
+    email: 'admin@admin.com',
+    employer: {
+      name: 'Médiateur',
+      validated: true,
+    },
+    job: {
+      hasPersonalOffer: true,
+      name: 'CNFS',
+      validated: true,
+    },
+  },
+  {
+    id: '627b85aea0466f0f132e1594',
+    surname: 'Bastien',
+    name: 'Dumont',
+    email: 'admin@admin.com',
+    employer: {
+      name: 'Pimms',
+      validated: true,
+    },
+    job: {
+      hasPersonalOffer: true,
+      name: 'CNFS',
+      validated: true,
+    },
+  },
+] as IUser[];