# ElasticSearch Smart Collection Search

**URL:** <https://community.forestadmin.com/t/elasticsearch-smart-collection-search/2932>\
**Category:** Help me!\
**Tags:** howtos\
**Created:** [July 19, 2021, 2:00pm UTC](https://community.forestadmin.com/t/elasticsearch-smart-collection-search/2932 "2021-07-19T14:00:09Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Arda\_Yurdakul](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/arda_yurdakul/32/2334_2.png) [@Arda\_Yurdakul](https://community.forestadmin.com/u/Arda_Yurdakul)\
**Post date:** [July 19, 2021, 2:00pm UTC](https://community.forestadmin.com/t/elasticsearch-smart-collection-search/2932/1 "2021-07-19T14:00:09Z")

</div>

Hi,

I have followed the documentation below to create a smart collection through ElasticSearch:

> **[Interact with your Elasticsearch data](https://docs.forestadmin.com/woodshop/how-tos/create-a-smart-collection-with-elasticsearch/play-with-your-elasticsearch-data)**

I was able to create the 2 basic get routes but I am stuck on how to implement the search capability. I have set isSearchable to true in my forest file. How do I modify this route to enable the search function:

```
router.get('/logs', async (request, response, next) => {
try {
  const pageSize = Number(request?.query?.page?.size) || 20;
  const page = Number(request?.query?.page?.number) || 1;
  const search = request.query?.search;
  const options = { timezone: request.query?.timezone };

  let filters;
  try {
    filters = request.query?.filters && JSON.parse(request.query.filters);
  } catch (e) {
    filters = undefined;
  }

  const result = await elasticsearchHelper.functionSearch({
    page,
    pageSize,
    filters: filters || undefined,
    options,
  });

  const serializer = new RecordSerializer({ name: 'logs' });

  response.send({
    ...await serializer.serialize(result.results),
    meta: {
      count: result.count,
    }
  });
} catch (e) {
  next(e);
}

```

});

```
Dependecies:

"axios": "^0.21.1",
 "body-parser": "1.19.0",
"chalk": "~1.1.3",
"cookie-parser": "1.4.4",
"cors": "2.8.5",
"debug": "~4.0.1",
"dotenv": "~6.1.0",    
"@elastic/elasticsearch": "^7.13.0",
"elasticsearch-helper": "^1.15.2",
"express": "~4.17.1",
"express-jwt": "5.3.1",
"forest-express-sequelize": "^7.0.0",
"morgan": "1.9.1",
"mysql2": "~2.2.5",
"require-all": "^3.0.0",
"sequelize": "~5.15.1"
```

---

<div class="post-metadata">

**Author:** ![morganperre](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/morganperre/32/1296_2.png) [@morganperre](https://community.forestadmin.com/u/morganperre)\
**Post date:** [July 19, 2021, 3:01pm UTC](https://community.forestadmin.com/t/elasticsearch-smart-collection-search/2932/2 "2021-07-19T15:01:52Z")

</div>

Hello @Arda_Yurdakul 👋

> ⚠ **search** is different from **filters**

The search functionality is the most painful to code. You have to hard code your own way to search your data. In this example you have a simple use case.

> **[Another example](https://docs.forestadmin.com/woodshop/how-tos/create-a-smart-collection-with-elasticsearch/display-elasticsearch-data)**

**Here’s an example that handle search**

```javascript
  ...

  const search = request.query?.search;

  // Declare the filters query retrieval first
  try {
    filters = request.query?.filters && JSON.parse(request.query.filters);
  } catch (e) {
    filters = undefined;
  }

  if (search) {
    // In case of search you need to handle it

    // NOTICE: Create a custom boolean query for Elasticsearch
    const booleanQuery = {
      should: [{
        terms: {
          fieldYouNeedToSearchOn: search,
        },
      }],
      minimum_should_match: 1,
    };
    
    // NOTICE: Use the elasticsearchHelper to query Elasticsearch
    const [results, count] = await Promise.all([
      elasticsearchHelper.esSearch(
        { page, pageSize },
        booleanQuery,
      ),
      elasticsearchHelper.esCount(booleanQuery),
    ]);
    
    response.send({
      ...await serializer.serialize(results),
      meta: {
        count: count,
      }
    });
  } else {
   // The already existing code that retrieve records using filters
   const result = await elasticsearchHelper.functionSearch({
      page,
      pageSize,
      filters: filters || undefined,
      options,
   });

   const serializer = new RecordSerializer({ name: 'logs' });

   response.send({
     ...await serializer.serialize(result.results),
     meta: {
       count: result.count,
     }
   });
 }

} catch (e) {
  next(e);
}

```

In this example you cannot search and filter at the same time. To do so you need to change the search part

```javascript
// import esTranslateFilter
const { esTranslateFilter } = require('../utils/filter-translator');

...

// AFTER - NOTICE: Create a custom boolean query for Elasticsearch
booleanQuery = { ...booleanQuery, filter: esTranslateFilter(elasticsearchHelper.filterDefinition, filters, options)};

...

```

[Finally you can find some documentation about boolean queries !](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html)

Let me know if it helps.  
Have a nice day. 🙂

Morgan

---

<div class="post-metadata">

**Author:** ![Arda\_Yurdakul](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/arda_yurdakul/32/2334_2.png) [@Arda\_Yurdakul](https://community.forestadmin.com/u/Arda_Yurdakul)\
**Post date:** [July 19, 2021, 4:03pm UTC](https://community.forestadmin.com/t/elasticsearch-smart-collection-search/2932/3 "2021-07-19T16:03:53Z")

</div>

> [@morganperre](#):
>
> `esTranslateFilter`

Hi Morgan,

Thank you for your in-depth explanation! It made sense to me but I ran into a nasty error whilst trying to implement the search functionality.

 ![image](https://europe1.discourse-cdn.com/flex013/uploads/forest/original/2X/6/63c16cd0651a2956a7f2f608056401814d6611ba.png)

I’m not quite sure what the problem is. Here are my field definitions and my boolQuery:

 ![image](https://europe1.discourse-cdn.com/flex013/uploads/forest/original/2X/f/f45f13ab62f55f80cedd565bfd6ffd478935fbb7.png)

 ![image](https://europe1.discourse-cdn.com/flex013/uploads/forest/original/2X/4/4d6e75a9eeecf29dd53c49d85a49363d27bcda60.png)

Thank you once again!

---

<div class="post-metadata">

**Author:** ![morganperre](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/morganperre/32/1296_2.png) [@morganperre](https://community.forestadmin.com/u/morganperre)\
**Post date:** [July 19, 2021, 4:31pm UTC](https://community.forestadmin.com/t/elasticsearch-smart-collection-search/2932/4 "2021-07-19T16:31:32Z")

</div>

Hey again @Arda_Yurdakul,

This error is specific to Elastocsearch. It’s due to the type of the `charge_point_identity` in your ES shard. I think you should use a **must query** with **match** in this case ?  
I let you check the matching you want to implement here: [Boolean query | Elasticsearch Guide [7.13] | Elastic](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html)

Some example of booleanQuery

```javascript
// strict matching example
must: {
    match: {
      charge_point_identity: search,
    }
}

// start with example
filter: {
 wildcard: {
      charge_point_identity: {
        value: `${search}*`,
        case_insensitive: true,
      },
    },
}

```

Have a nice day,  
Morgan

---

<div class="post-metadata">

**Author:** ![Arda\_Yurdakul](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/arda_yurdakul/32/2334_2.png) [@Arda\_Yurdakul](https://community.forestadmin.com/u/Arda_Yurdakul)\
**Post date:** [July 19, 2021, 7:16pm UTC](https://community.forestadmin.com/t/elasticsearch-smart-collection-search/2932/5 "2021-07-19T19:16:00Z")

</div>

Yes, it works now! Very helpful, thank you!
