diff --git a/src/app/elasticsearch/services/elasticsearch.service.ts b/src/app/elasticsearch/services/elasticsearch.service.ts
index ac3d122b7ad431f6e5651ba21f5b30822a75ef68..92918b47943cbcaf894fb502157eac56014a39cd 100644
--- a/src/app/elasticsearch/services/elasticsearch.service.ts
+++ b/src/app/elasticsearch/services/elasticsearch.service.ts
@@ -6,7 +6,6 @@ import { geosource, notificationMessages } from '../../../i18n/traductions';
 import { ErrorService } from '../../core/services';
 import { APP_CONFIG } from '../../core/services/app-config.service';
 import { scopesResearch } from '../../shared/variables';
-// tslint:disable-next-line: max-line-length
 import { Aggregation, ElasticsearchOptions, Filter, IElasticsearchResponse, IPostsESOptions } from '../models';
 
 @Injectable()
@@ -128,7 +127,7 @@ export class ElasticsearchService {
     }
 
     if (options.searchString !== '') {
-      const searchString = this.escapeSpecialCharacters(options.searchString, options.fromAutocompletion);
+      const searchString = this.escapeSpecialCharacters(options.searchString, options.fromAutocompletion, 'AND');
       body.query.bool['must'] = [
         {
           query_string: {
@@ -622,7 +621,7 @@ export class ElasticsearchService {
   /**
   * Escape special characters except logical operators.
   * */
-  escapeSpecialCharacters(searchString, fromAutocompletion) {
+  escapeSpecialCharacters(searchString: string, fromAutocompletion: boolean, joinOperator = '+') {
 
     let escapedSearchString = '';
     /** If the request:
@@ -639,7 +638,7 @@ export class ElasticsearchService {
 
       // We join each words with the '+' logical operator to accurate the results
       const words = escapedSearchString.split(/\s+/);
-      escapedSearchString = words.join(' + ');
+      escapedSearchString = words.join(` ${joinOperator} `);
 
       /** If not all this, we don't escape the "()" (and will be interpreted as logical characters by ES)
        *  but we still do escape some other special characters
diff --git a/src/app/map/components/map.component.html b/src/app/map/components/map.component.html
index 9d5941967ad1a51df615fb128b2df9479642c89d..a8d91a08cb13d173b33fe8db9d6eaad089a46f98 100644
--- a/src/app/map/components/map.component.html
+++ b/src/app/map/components/map.component.html
@@ -24,6 +24,7 @@
             </svg>
           </ng-template>
         </button>
+
         <div class="buttons has-addons column-content is-hidden-mobile">
           <ng-container *ngFor="let l of settings.baseLayers">
             <button class="button selectBase" [disabled]="l.id === selectedBaseLayer.id"
@@ -34,6 +35,12 @@
           </ng-container>
         </div>
       </div>
+      <div class="button-3d" *ngIf="displayButton3d">
+        <button class="button" [ngClass]="{'is-active': display3d}"
+        (click)="switch3DLayer()" *ngIf="selectedBaseLayer.id===settings.baseLayers[0].id">
+          3D
+        </button>
+      </div>
       <div class="column is-narrow is-hidden-mobile">
         <app-search-address [optionsAutocomplete]="searchLocationResult" (searchAddress)="searchAdress($event)"
           (addressSelected)="flyTo($event)" (clearAddress)="removeMarker()">
@@ -43,20 +50,17 @@
   </div>
 
   <div class="geolocation-container">
-    <button class="geolocation button is-medium" type="button" 
-    i18n-aria-label="@@dataset.detail.map.center" aria-label="Center to my position"
-    (click)="centerToMyPosition()">
+    <button class="geolocation button is-medium" type="button" i18n-aria-label="@@dataset.detail.map.center"
+      aria-label="Center to my position" (click)="centerToMyPosition()">
     </button>
   </div>
 
+
   <div class="copy-map">
     <input type="text" class="input" id="mapUrlCopy" i18n-aria-label="@@dataset.detail.map.share"
-      aria-label="Share the map"
-    [value]="mapUrl()" #mapUrlElement>
+      aria-label="Share the map" [value]="mapUrl()" #mapUrlElement>
     <button class="button is-medium has-tooltip-left tooltip" i18n-aria-label="@@dataset.detail.map.share"
-      aria-label="Share the map"
-    type="button" (click)="copyMaplink(mapUrlElement)" 
-    [attr.data-tooltip]="shareMessage">
+      aria-label="Share the map" type="button" (click)="copyMaplink(mapUrlElement)" [attr.data-tooltip]="shareMessage">
       <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" viewBox="0 0 20 20">
         <path fill="#818080" fill-rule="evenodd"
           d="M1.852 7.777a2.619 2.619 0 0 1 0-3.703l2.222-2.222a2.619 2.619 0 0 1 3.704 0l2.963 2.963a2.619 2.619 0 0 1 0 3.703l-.37.37.74.741.37-.37a2.619 2.619 0 0 1 3.704 0l2.963 2.963a2.619 2.619 0 0 1 0 3.704l-2.222 2.222a2.619 2.619 0 0 1-3.704 0L9.26 15.185a2.619 2.619 0 0 1 0-3.704l.37-.37-.74-.741-.37.37a2.619 2.619 0 0 1-3.704 0L1.852 7.777zm7.037-.37l-.74-.74a1.048 1.048 0 0 0-1.482 1.48l.74.742-.37.37a.524.524 0 0 1-.74 0L3.332 6.296a.524.524 0 0 1 0-.74l2.223-2.223a.524.524 0 0 1 .74 0L9.26 6.296a.524.524 0 0 1 0 .74l-.37.371zm2.222 5.185l-.37.37a.524.524 0 0 0 0 .742l2.963 2.962a.524.524 0 0 0 .74 0l2.223-2.222a.524.524 0 0 0 0-.74l-2.963-2.963a.524.524 0 0 0-.741 0l-.37.37.74.74a1.047 1.047 0 1 1-1.481 1.482l-.74-.74z"
diff --git a/src/app/map/components/map.component.scss b/src/app/map/components/map.component.scss
index 25b28dd5408739a5767150e1bd7ba2b3d7f59a5f..a676ba2eece41da44aa6c4ceb05276893970dc6f 100644
--- a/src/app/map/components/map.component.scss
+++ b/src/app/map/components/map.component.scss
@@ -61,6 +61,23 @@
   border: none;
 }
 
+.button-3d {
+  position: absolute;
+  top: 50px;
+  right: 0;
+
+  @media screen and (min-width: $tablet) {
+    left: 0;
+  }
+
+  & > .button.is-active {
+    background-color: $blue-color;
+    color: white;
+  }
+}
+
+
+
 .copy-map,
 .geolocation-container {
   position: absolute;
diff --git a/src/app/map/components/map.component.ts b/src/app/map/components/map.component.ts
index 3ae47dcbc17242844936caf820ee332fb691fb78..a4ebce8614219fca9ee443dcd2e77b703a69fb6f 100644
--- a/src/app/map/components/map.component.ts
+++ b/src/app/map/components/map.component.ts
@@ -31,6 +31,7 @@ export class MapComponent implements OnInit, OnDestroy {
   // Key of the lay to be displayed from baseLayers in environment files
   selectedBaseLayer = this.settings.baseLayers[this.settings.defaultBaseLayer];
   displayPitchSlider = false;
+  displayButton3d = false;
   display3d = false;
 
   // Attributes to manage the display of the pudate map button
@@ -39,8 +40,6 @@ export class MapComponent implements OnInit, OnDestroy {
   previousDatasetId: string;
   availableLayers: string[];
 
-  baseLayer3d = 1;
-
   geolocation = false;
 
   searchLocationResult = [];
@@ -206,12 +205,30 @@ export class MapComponent implements OnInit, OnDestroy {
       this.map.on('style.load', () => {
         this._mapService.addLayers();
       });
+
+      this.map.on('zoomend', () => {
+        if (this.map.getZoom() < 14) {
+          this.displayButton3d = false;
+
+          if (this.map.getLayer('3d-layer')) {
+            // this.display3d = false;
+            this.map.removeLayer('3d-layer');
+          }
+
+        } else if (this.map.getZoom() > 14) {
+          this.displayButton3d = true;
+          if (this.display3d) {
+            this._mapService.switch3DLayer();
+          }
+        }
+      });
     }
   }
 
   switchLayer(baseLayer) {
     this.selectedBaseLayer = baseLayer;
     this._mapService.switchLayer(baseLayer);
+    this.display3d = false;
   }
 
   // [WARNING] This toggle only works with two base layers
@@ -222,6 +239,7 @@ export class MapComponent implements OnInit, OnDestroy {
       this.selectedBaseLayer = this.settings.baseLayers[0];
     }
     this._mapService.switchLayer(this.selectedBaseLayer);
+    this.display3d = false;
   }
 
   // Looks for the language to be used, if not indicated in the url takes the navigator default language
@@ -239,7 +257,7 @@ export class MapComponent implements OnInit, OnDestroy {
 
   switch3DLayer() {
     if (this.map.isStyleLoaded()) {
-      if (this.map.getSource('openmaptiles')) {
+      if (this.map.getSource('3d-source')) {
         this.display3d = !this.display3d;
         this._mapService.switch3DLayer();
       }
diff --git a/src/app/map/services/map.service.ts b/src/app/map/services/map.service.ts
index 1e8f760ae1bc7ff656c14541b5dadb828562b515..03f970b68c2bac04a9fcfe6e140a6e532fa5ce51 100644
--- a/src/app/map/services/map.service.ts
+++ b/src/app/map/services/map.service.ts
@@ -8,12 +8,10 @@ import { Notification } from '../../core/models';
 import { NotificationService } from '../../core/services';
 import { APP_CONFIG } from '../../core/services/app-config.service';
 import { DataType, MapOptions } from '../models/map-options';
-import { settings } from '../settings';
 
 @Injectable()
 export class MapService {
 
-  settings = settings;
   private _map: mapboxgl.Map;
   private url: string;
   selectedBaseLayer: any;
@@ -22,11 +20,10 @@ export class MapService {
   eventPopupAdded = false;
   mapIsConstructed: boolean = false;
 
-  // Map
+  // Map features colors
   featureColor: string = '#1d92ff';
   featureHoverColor: string = '#E19190';
   featureHighlightedColor: string = '#da322f'; // Tomato color
-  visitedColor: string = '#4668ab';
 
   hoveredFeatureId: string;
   highlightedFeatureId: string;
@@ -46,8 +43,6 @@ export class MapService {
     this.featureHighlightedColor,
     ['boolean', ['feature-state', 'hover'], false],
     this.featureHoverColor,
-    ['boolean', ['feature-state', 'visited'], false],
-    this.visitedColor,
     'transparent',
   ];
 
@@ -55,6 +50,7 @@ export class MapService {
     private _notificationService: NotificationService,
   ) { }
 
+  // Init the map with basic options for controls, transform request etc...
   createMap(
     mapOptions: MapOptions,
     url: string, baseLayer: any, options?: mapboxgl.MapboxOptions): mapboxgl.Map {
@@ -108,10 +104,22 @@ export class MapService {
     return this._map;
   }
 
+  // This adds 2 layers:
+  // - a WMS layer to display the visual part of the features (WMS service send a png or jpeg)
+  // - a data layer, created from a geojson or an MVT service. It is used for the features interaction (hover, click)
   addLayers() {
     this.addWMSLayer();
 
-    // Add a geojson layer only if data from the metropole
+    // Add the 3d source. Constructed with MVT tiles from the 'fpc_fond_plan_communaut.fpctoit' dataset
+    const domain = this.mapOptions.vectorService.url.split('wfs')[1];
+    const url = `${this.mapOptions.mvtUrl}${domain}?LAYERS=
+fpc_fond_plan_communaut.fpctoit&map.imagetype=mvt&tilemode=gmap&tile={x}+{y}+{z}&mode=tile`;
+    this._map.addSource('3d-source', {
+      type: 'vector',
+      tiles: [url],
+    });
+
+    // Add the data layer only if it comes from the Lyon Metropole
     if (this.mapOptions.rasterService.url.includes(APP_CONFIG.backendUrls.wms)) {
       // There is two ways to add tha data layers: from a geojson or from a MVT url
       if (!this.mapOptions.isMVT) {
@@ -153,7 +161,7 @@ export class MapService {
 
       // Set highlited style for the current feature
       this.highlightedFeatureId = this.selectedFeature;
-      this.changeFeatureState(this.highlightedFeatureId, { visited: true, highlight: true });
+      this.changeFeatureState(this.highlightedFeatureId, { highlight: true });
 
       if (e.point.x > (this._map.getCanvas().width - 400)) {
         // If the screen is not mobile the dataset data details panel push the map that is then smaller
@@ -206,7 +214,6 @@ export class MapService {
 
   // Add the raster (WMS) layer
   addWMSLayer() {
-    // ------------------- WMS Source & Layer -------------------
     this._map.addSource('wms-source', {
       type: 'raster',
       tiles: [
@@ -225,10 +232,11 @@ export class MapService {
 
   }
 
+  // Add the data layer (from geojson or MVT)
   addDataLayer() {
-
     let layerOptions = {};
 
+    // Set the paint options depending the geometry type
     // For 'Polygon' and 'MultiPolygon' features
     if (this.mapOptions.dataType.isAreal) {
       layerOptions = {
@@ -236,15 +244,12 @@ export class MapService {
         paint: {
           'fill-color': this.COLOR_EXPRESSION,
           'fill-opacity': 0.7,
-          'fill-outline-color': ['case',
-            ['boolean', ['feature-state', 'visited'], false],
-            'white',
-            'transparent',
-          ],
+          'fill-outline-color': 'transparent',
         },
       };
     }
 
+    // For 'Line' and 'MultiLine' features
     if (this.mapOptions.dataType.isLinear) {
       layerOptions = {
         type: 'line',
@@ -259,9 +264,8 @@ export class MapService {
       };
     }
 
+    // For "Point" features
     if (this.mapOptions.dataType.isPunctual) {
-      // Add layer + style for the points
-      // Get paint options depending the dataset size
       layerOptions = {
         type: 'circle',
         paint: {
@@ -274,15 +278,11 @@ export class MapService {
           'circle-stroke-width': ['case',
             ['boolean', ['feature-state', 'highlight'], false],
             5,
-            ['boolean', ['feature-state', 'visited'], false],
-            1,
             0,
           ],
           'circle-stroke-color': ['case',
             ['boolean', ['feature-state', 'highlight'], false],
             this.featureHighlightedColor,
-            ['boolean', ['feature-state', 'visited'], false],
-            'white',
             'transparent',
           ],
         },
@@ -294,11 +294,13 @@ export class MapService {
         id: 'data-layer',
         source: 'vector-source',
         ...layerOptions,
-        ...(this.mapOptions.isMVT ? { 'source-layer': this.mapOptions.vectorService.name } : {}), // if not MVT, this property is not needed
+        ...(this.mapOptions.isMVT ? { 'source-layer': this.mapOptions.vectorService.name } : {}), // if from MVT, this property is needed
       });
 
+    // If not already done, add all the events listeners
     if (!this.eventPopupAdded) {
-      // Manage the cursor and feature state for point-features layer when mouse events
+
+      // Manage the cursor and feature state for data layer when mouse events
       this._map.on('mousemove', 'data-layer', (e) => {
         this.manageFeatureOnMouseMove(e.features);
       });
@@ -331,10 +333,8 @@ export class MapService {
           );
         }
       });
-
       this.eventPopupAdded = true;
     }
-
   }
 
   manageFeatureOnMouseMove(features: any) {
@@ -364,40 +364,25 @@ export class MapService {
   }
 
   switch3DLayer() {
-    if (!this._map.getLayer('building-3d')) {
-      // Insert the layer beneath any symbol layer.
-      const layers = this._map.getStyle().layers;
-      let labelLayerId;
-
-      for (let i = 0; i < layers.length; i += 1) {
-        if (layers[i].type === 'symbol' && layers[i].layout['text-field']) {
-          labelLayerId = layers[i].id;
-          break;
-        }
-      }
+    if (!this._map.getLayer('3d-layer')) {
 
       this._map.addLayer(
         {
-          id: 'building-3d',
+          id: '3d-layer',
           type: 'fill-extrusion',
-          source: 'openmaptiles',
-          'source-layer': 'building',
+          source: '3d-source',
+          'source-layer': 'fpc_fond_plan_communaut.fpctoit',
           paint: {
-            'fill-extrusion-color': 'hsla(40, 37%, 50%, 1)',
+            'fill-extrusion-color': '#E0E4EF',
             'fill-extrusion-height': {
-              property: 'render_height',
+              property: 'htotale',
               type: 'identity',
             },
-            'fill-extrusion-base': {
-              property: 'render_min_height',
-              type: 'identity',
-            },
-            'fill-extrusion-opacity': 0.8,
+            'fill-extrusion-opacity': 0.7,
           },
-        },
-        labelLayerId);
+        });
     } else {
-      this._map.removeLayer('building-3d');
+      this._map.removeLayer('3d-layer');
     }
   }
 
@@ -430,7 +415,7 @@ export class MapService {
 
       // Set highlited style for the current feature
       this.highlightedFeatureId = this.selectedFeature;
-      this.changeFeatureState(this.highlightedFeatureId, { visited: true, highlight: true });
+      this.changeFeatureState(this.highlightedFeatureId, { highlight: true });
 
       const pointCenter = selectedFeature.geometry.type === 'Point' ?
         selectedFeature.geometry.coordinates : centroid(selectedFeature).geometry.coordinates;
@@ -448,31 +433,56 @@ export class MapService {
 
   /*
   * When the search value has been changed, we add a text expression
-  * that filters the features containing this text value in one of its properties.
+  * that filters the features containing this text value in at least one of its properties.
   * If there is a match we:
   * - decrease the opacity for the raster layer (WMS) which displays all the features
   * - show the found features from our data layer (WMT or GeoJSON)
   */
   filterBySearchValue(searchValue: string, properties: string[]) {
 
-    const filters = [];
     if (searchValue) {
 
-      // Add the "in" expression (look for substring in string). To make it case insensitive, set 
-      // both the text value and the property value to uppercase.
-      properties.forEach((property) => {
-        filters.push(['in', ['upcase', searchValue], ['upcase', ['to-string', ['get', property]]]]);
+      const escapedSearchString = searchValue.replace(/[\=~><\"\?^\${}\(\)\|\&\:\!\/[\]\\]/g, '\\$&');
+      const words = escapedSearchString.split(/\s+/);
+
+      // Some basic explanations for the operators expression we use:
+      // - "all": returns true if all the conditions are true
+      // - "any": returns true if one of the the conditions are true
+      // - "in":  can be used in many context, here it looks for a substring in a string. To make it case insensitive, set
+      // both the search value and the property value to uppercase with the operator 'upcase'.
+      // To learn more about it: https://docs.mapbox.com/mapbox-gl-js/style-spec/#expressions
+      // Here is the format of the expression, for example with 2 words:
+      // ['all',
+      //   ['any',
+      //      ['in', ['upcase', 'word1'], ['upcase', ['to-string', ['get', property1]]]],
+      //      ['in', ['upcase', 'word1'], ['upcase', ['to-string', ['get', property2]]]],
+      //      ['in', ['upcase', 'word1'], ['upcase', ['to-string', ['get', property3]]]]
+      //   ],
+      //   ['any',
+      //      ['in', ['upcase', 'word2'], ['upcase', ['to-string', ['get', property1]]]],
+      //      ['in', ['upcase', 'word2'], ['upcase', ['to-string', ['get', property2]]]],
+      //      ['in', ['upcase', 'word2'], ['upcase', ['to-string', ['get', property3]]]]
+      //   ],
+      // ]
+      const anyFilter = [];
+      words.forEach((word) => {
+        const propertiesFilters = [];
+        properties.forEach((property) => {
+          propertiesFilters.push(['in', ['upcase', word], ['upcase', ['to-string', ['get', property]]]]);
+        });
+        anyFilter.push(['any', ...propertiesFilters]);
       });
 
-      // For each type layer if exists (point, line, polyon), add this filter and set a color to replace transparent
-      const copyColor = [...this.COLOR_EXPRESSION]
-      copyColor.splice(copyColor.length - 1, 0, ['any', ...filters], 'green');
+      // Once this search filter expression is done, we add it to the existing paint options (for hover, selected)
+      // of the data-layer
+      const copyPaintOptions = [...this.COLOR_EXPRESSION];
+      copyPaintOptions.splice(copyPaintOptions.length - 1, 0, ['all', ...anyFilter], 'green');
 
-      this.paintPropertyForLayer('data-layer', this.mapOptions.dataType, copyColor);
+      this.paintPropertyForLayer('data-layer', this.mapOptions.dataType, copyPaintOptions);
       this._map.setPaintProperty('wms-layer', 'raster-opacity', 0.5);
 
     } else {
-      // If value is empty, remove the filter and set the opacity for the raster layer back to 1.
+      // If value is empty, remove the search expression and set the opacity for the raster layer back to 1.
       this.paintPropertyForLayer('data-layer', this.mapOptions.dataType, this.COLOR_EXPRESSION);
       this._map.setPaintProperty('wms-layer', 'raster-opacity', 1);
 
diff --git a/src/app/map/settings.ts b/src/app/map/settings.ts
index ca5bacf5c07384c10046673c8c9f9b749360cb4f..b08e25eca920f32fad8eeb37b1fb6962251554cd 100644
--- a/src/app/map/settings.ts
+++ b/src/app/map/settings.ts
@@ -1,5 +1,4 @@
 export const settings = {
-  maxDisplayFeatures: 500,
 
   // Map
   defaultBaseLayer: 0,