# Filter on smart field/ smart relationship

**URL:** <https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534>\
**Category:** Help me!\
**Created:** [October 13, 2021, 10:32pm UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534 "2021-10-13T22:32:23Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![mostafa\_hatem](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/mostafa_hatem/32/2347_2.png) [@mostafa\_hatem](https://community.forestadmin.com/u/mostafa_hatem)\
**Post date:** [October 13, 2021, 10:32pm UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/1 "2021-10-13T22:32:23Z")

</div>

{

```
  field: "projectID",

  type: "String",

  reference: "projects._id",

  isFilterable: true,

  get: function (result) {

    return projects.findById(result.projectID)._id;

  },

},

```

## Expected behavior

I want to filter on the smart field using only the projectId (id of relation) but it forces a dropdown menu (sub field) with all the attributes of the relation and when i choose the id and try to filter with it i get the following error  
[forest] 🌳🌳🌳 Unexpected error: “filter” method missing on smart field “projectID”

I want to be only able to filter by id which is a mongoose objectId what should i do

## Context

```
"express": "~4.17.1",

"express-jwt": "6.0.0",

"forest-express-mongoose": "^8.0.0",

"mongoose": "~5.8.2",

```

- Project Name: simulationService

---

<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:** [October 14, 2021, 8:24am UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/2 "2021-10-14T08:24:01Z")

</div>

Hello @mostafa_hatem,

Ok, you need to define a **filter** hooks in your Smart Field in order to provide a way to filter the smart filed.

[You can find the related documentation here.](https://docs.forestadmin.com/documentation/reference-guide/fields/create-and-manage-smart-fields#filtering)

Let me know if it help !

Kind regards,  
Morgan

---

<div class="post-metadata">

**Author:** ![mostafa\_hatem](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/mostafa_hatem/32/2347_2.png) [@mostafa\_hatem](https://community.forestadmin.com/u/mostafa_hatem)\
**Post date:** [October 14, 2021, 9:42am UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/3 "2021-10-14T09:42:52Z")

</div>

but how to prevent it from having a subfield when filtering or allowing the subfield only to be the id

---

<div class="post-metadata">

**Author:** ![mostafa\_hatem](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/mostafa_hatem/32/2347_2.png) [@mostafa\_hatem](https://community.forestadmin.com/u/mostafa_hatem)\
**Post date:** [October 14, 2021, 10:01am UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/4 "2021-10-14T10:01:06Z")

</div>

I also encountered this error  
[forest] 🌳🌳🌳 Unexpected error: Cast to ObjectId failed for value “55f” at path “\_id” for model “projects”  
I expected it to find no results not give me a server error

---

<div class="post-metadata">

**Author:** ![mostafa\_hatem](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/mostafa_hatem/32/2347_2.png) [@mostafa\_hatem](https://community.forestadmin.com/u/mostafa_hatem)\
**Post date:** [October 14, 2021, 10:15am UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/5 "2021-10-14T10:15:22Z")

</div>

{

```
  field: "projectID",

  type: "String",

  reference: "projects._id",

  isFilterable: true,

  get: function (result) {

    return projects.findById(result.projectID)._id;

  },

  filter({ condition, where }) {

    const value = !!condition.value && condition.value;

    switch (condition.operator) {

      case "in":

        return {

          projectID: value,

        };

      default:

        return null;

    }

  },

},

```

can you please explain how to use the filter function you can see the code above and the condition under in the screenshot and i got no results found

 ![newscc](https://europe1.discourse-cdn.com/flex013/uploads/forest/original/2X/0/01fe0577276fbbfc47ef8bbbcfe2b85f7a9aaf61.png)  
Also is there a way to to remove the second drop down which chooses a field in the relation and make it filter on the id by default? and the conditions dropdown show all the options but I only have one in the switch case so using other options gives error

---

<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:** [October 14, 2021, 10:52am UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/6 "2021-10-14T10:52:16Z")

</div>

Hello again @mostafa_hatem,

The **projectID** is a **Smart Field** (_kind of a data you have built even if in your case it’s just an id of a related data_) and when you filter your data this SmartField does not really exist in your record.

- First thing first, does the get function work ? The code `projects.findById(result.projectID)._id;` seems weird since result does not have any projectID ?

- Then for the filter part you need to implements the filters you want to be available. Here’s the list of all filters (_equivalent to condition.operator in the code_): `not, greater_than, less_than, contains, starts_with, ends_with, not_contains, present, not_equal, blank, equal, includes_all, in`

- The you have very complicated business logic. You can use complexe queries (to compute idsThatMatchsProjectId) then to build the real filter condition ` return { _id: { $in: [idsThatMatchsProjectId] } }`. [We have an example for the segment that can inspire you.](https://docs.forestadmin.com/documentation/reference-guide/segments/smart-segments#creating-a-smart-segment)

[https://docs.forestadmin.com/documentation/reference-guide/segments/smart-segments](https://docs.forestadmin.com/documentation/reference-guide/segments/smart-segments)

> Simple example (This should not work since I don’t understand if projectID is part of your record or not see my comment on get hook)
> 
> ```javascript
> filter({ condition, where }) {
> const value = !!condition.value && condition.value;
> 
> switch (condition.operator) {
> // Define equal operator
> case 'equal':
> return { projectID: value };
> 
> default:
> return null;
> }
> }
> },
> 
> ```

---

<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:** [October 14, 2021, 10:55am UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/7 "2021-10-14T10:55:44Z")

</div>

> [@mostafa\_hatem](#):
>
> Also is there a way to to remove the second drop down which chooses a field in the relation and make it filter on the id by default? and the conditions dropdown show all the options but I only have one in the switch case so using other options gives error

And reading at this, I’m wondering. Do you want just to be able to filter on _projectID_ ?

The answer is yes for filtering, you need to set `isFilterable: false,` for all the fields you don’t want your users to be able to filter.

---

<div class="post-metadata">

**Author:** ![mostafa\_hatem](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/mostafa_hatem/32/2347_2.png) [@mostafa\_hatem](https://community.forestadmin.com/u/mostafa_hatem)\
**Post date:** [October 14, 2021, 11:46am UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/8 "2021-10-14T11:46:04Z")

</div>

projects.findById(result.projectID).\_id this works fine as I get a link to the project in viewing and it works just fine

---

<div class="post-metadata">

**Author:** ![mostafa\_hatem](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/mostafa_hatem/32/2347_2.png) [@mostafa\_hatem](https://community.forestadmin.com/u/mostafa_hatem)\
**Post date:** [October 14, 2021, 11:59am UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/9 "2021-10-14T11:59:06Z")

</div>

"And reading at this, I’m wondering. Do you want just to be able to filter on _projectID_ ?

The answer is yes for filtering, you need to set `isFilterable: false,` for all the fields you don’t want your users to be able to filter."  
what i actually meant is that the projectID is a relation so i Just want to filter on the id of the relation not the other attributes so i don’t want a subfield  
 ![sub](https://europe1.discourse-cdn.com/flex013/uploads/forest/original/2X/8/8c72da6a0c2e0c3554342d04569255871283e765.png)

---

<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:** [October 14, 2021, 12:34pm UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/10 "2021-10-14T12:34:47Z")

</div>

> [@mostafa\_hatem](#):
>
> projects.findById(result.projectID).\_id this works fine as I get a link to the project in viewing and it works just fine

I just not quite understand why you need to do `projects.findById(result.projectID)._id` since `projectID` is the same value ? Am I right ?

> [@mostafa\_hatem](#):
>
> what i actually meant is that the projectID is a relation so i Just want to filter on the id of the relation not the other attributes so i don’t want a subfield

Sorry, I didn’t understood it quite well. 😕

The answer is no, (you can remove them if you disable isFilterable for the fields you don’t want to be filterable in the project collection)  
**but** you can use the search hook and only make this field searchable ?

```javascript
search(search) {
  // Example search with projectID start with the search of the user
  const startWithRegex = new RegExp('^' + search);
  return { projectID: startWithRegex };
},

// Or simple exact match
search(search) {
  return { projectID: search };
},

```

---

<div class="post-metadata">

**Author:** ![mostafa\_hatem](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/mostafa_hatem/32/2347_2.png) [@mostafa\_hatem](https://community.forestadmin.com/u/mostafa_hatem)\
**Post date:** [October 14, 2021, 7:54pm UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/11 "2021-10-14T19:54:21Z")

</div>

projects.findById(result.projectID).\_id is a mistake it should be projects.findById(result.projectID)  
as the field projectID is a smart relationship when I come to filter it shows me the subfield as shown in the screenshot when I implement the filter function as below and use the operator “is” with a value that is there it gives me no results found… do I have to implement the filter function in a different way because it is a smart relationship  
{

```
  field: "projectID",

  type: "String",

  reference: "projects._id",

  isFilterable: true,

  get: function (result) {

    return projects.findById(result.projectID);

  },

  filter({ condition, where }) {

    const value = !!condition.value && condition.value; // array of ids

    switch (condition.operator) {

      case "in":

        return { projectID: { $in: value } };

      default:

        return null;

    }

  },

},
```

---

<div class="post-metadata">

**Author:** ![mostafa\_hatem](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/mostafa_hatem/32/2347_2.png) [@mostafa\_hatem](https://community.forestadmin.com/u/mostafa_hatem)\
**Post date:** [October 15, 2021, 6:10pm UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/12 "2021-10-15T18:10:58Z")

</div>

I realized that references attribute is enough for creating a smart relation and I don’t need a get function i misunderstood it but I still think I am implementing the filter function incorrectly so can anyone please help me with that

---

<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:** [October 18, 2021, 7:54am UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/13 "2021-10-18T07:54:25Z")

</div>

Hello @mostafa_hatem,

What do you want to implement ? I think you can remove this filter hook (function) too. If you don’t want a specific behaviour let the default one.

Let me know what you want to achieve.

Regards,  
Morgan

---

<div class="post-metadata">

**Author:** ![mostafa\_hatem](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/mostafa_hatem/32/2347_2.png) [@mostafa\_hatem](https://community.forestadmin.com/u/mostafa_hatem)\
**Post date:** [October 18, 2021, 8:58am UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/14 "2021-10-18T08:58:13Z")

</div>

I want the default behavior but if i remove the filter function, this error occurs Unexpected error: “filter” method missing on smart field “projectID”

---

<div class="post-metadata">

**Author:** ![mostafa\_hatem](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/mostafa_hatem/32/2347_2.png) [@mostafa\_hatem](https://community.forestadmin.com/u/mostafa_hatem)\
**Post date:** [October 18, 2021, 8:58am UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/15 "2021-10-18T08:58:46Z")

</div>

I only want to implement default filtering on my smart relation field

---

<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:** [October 18, 2021, 9:39am UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/16 "2021-10-18T09:39:46Z")

</div>

I’m not sure to have all the informations to help you.

Can you share your mongoose model for this collection ? I’m wondering if you already define `projectID` in your model.

Plus, [you can this the documentation to create native belong-to relationship](https://docs.forestadmin.com/documentation/reference-guide/relationships#adding-a-belongsto-relationship).  
Also, [the documentation for smart relationship, the your are trying to implement](https://docs.forestadmin.com/documentation/reference-guide/relationships/create-a-smart-relationship#creating-a-belongsto-smart-relationship).

Regards,  
Morgan

---

<div class="post-metadata">

**Author:** ![mostafa\_hatem](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/mostafa_hatem/32/2347_2.png) [@mostafa\_hatem](https://community.forestadmin.com/u/mostafa_hatem)\
**Post date:** [October 18, 2021, 10:27pm UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/17 "2021-10-18T22:27:13Z")

</div>

**results model:**

```javascript

// This model was generated by Forest CLI. However, you remain in control of your models.

// Learn how here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models

module.exports = (mongoose, Mongoose) => {

  // This section contains the properties of your model, mapped to your collection's properties.

  // Learn more here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models#declaring-a-new-field-in-a-model

  const schema = Mongoose.Schema(

    {

      resources: { type: [Mongoose.Schema.Types.ObjectId], ref: 'resources' },

      technologies: {

        type: [Mongoose.Schema.Types.ObjectId],

        ref: 'technologies',

      },

      loads: { type: [Mongoose.Schema.Types.ObjectId], ref: 'loads' },

      carriers: { type: [Mongoose.Schema.Types.ObjectId], ref: 'carriers' },

      lifeTime: Number,

      projectID: Mongoose.Schema.Types.ObjectId,

    },

    {

      timestamps: false,

    }

  )

  return mongoose.model('results', schema, 'results')

}

```

**project model in another database i want a smart relation with:**

```javascript

// This model was generated by Forest CLI. However, you remain in control of your models.

// Learn how here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models

module.exports = (mongoose, Mongoose) => {

  // This section contains the properties of your model, mapped to your collection's properties.

  // Learn more here: https://docs.forestadmin.com/documentation/v/v6/reference-guide/models/enrich-your-models#declaring-a-new-field-in-a-model

  const schema = Mongoose.Schema({

    'city': String,

    'company': String,

    'created_at': Date,

    'configuration': {

      'general': {

        'lifetime': Number,

        'interestRate': Number,

        'kpi': {

          'cpx': Object,

          'opx': Object,

        },

        'latitude': Object,

        'longitude': Object,

        'inflationRate': Number,

        'budget': String,

        'notes': String,

        'fixedOpex': String,

        'fixedCapex': String,

      },

      'revision': Number,

      'system': {

        'budget': Number,

        'network': {

          'revision': Number,

        },

      },

    },

    'icon': String,

    'street': String,

    'importance_capex': Number,

    'status': String,

    'importance_opex': Number,

    'capex': Boolean,

    'interest': Number,

    'electrical': Boolean,

    'updated_at': Date,

    'country': String,

    'heating': Boolean,

    'coo': Boolean,

    'importance_coo': Number,

    'domain': String,

    'cooling': Boolean,

    'lifetime': Number,

    'title': String,

    'discount': Number,

    'email': String,

    'opex': Boolean,

    'author': String,

    'description': String,

    'user_id': Number,

    'zipcode': Number,

  }, {

    timestamps: false,

  });

  return mongoose.model('projects', schema, 'projects');

};

```

**fields array in forest/results file:**

```javascript

fields: [

    {

      field: "projectID",

      type: "String",

      reference: "projects._id",

      isFilterable: true,

    },

  ],

```

the filtration is not working as it needs a filter function but i am not quite sure how to implement this on smart relation as a sub field appears in the filter

---

<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:** [October 19, 2021, 8:01am UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/18 "2021-10-19T08:01:36Z")

</div>

Hello @mostafa_hatem,

It’s much clear now. You have already a **relationship** in your code. **projectID** is already defined in your model. That why you can of struggle with SmartFields.

**SOLUTION 1**  
In your first model (results) replace

```javascript
projectID: Mongoose.Schema.Types.ObjectId,

```

by a true belongsTo relationship

```javascript
'projects_id': { type: Mongoose.Schema.Types.ObjectId, ref: 'projects' },

```

**SOLUTION 2**  
_(I do not advice other solution ! It would make your code harder than it needs to be.)_

Regards,  
Morgan

---

<div class="post-metadata">

**Author:** ![mostafa\_hatem](https://dub1.discourse-cdn.com/flex013/user_avatar/community.forestadmin.com/mostafa_hatem/32/2347_2.png) [@mostafa\_hatem](https://community.forestadmin.com/u/mostafa_hatem)\
**Post date:** [October 19, 2021, 8:19am UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/19 "2021-10-19T08:19:10Z")

</div>

solution 1 is not possible as they are in different databases so that is why i used a smart relation

---

<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:** [October 19, 2021, 9:46am UTC](https://community.forestadmin.com/t/filter-on-smart-field-smart-relationship/3534/20 "2021-10-19T09:46:50Z")

</div>

My bad @mostafa_hatem,

So you need the **SOLUTION 2** … I think the best solution for you is to add a **search** hook and not filters ! I already gave the answer.

> [@morganperre](#):
>
> ```javascript
> search(search) {
> // Example search with projectID start with the search of the user
> const startWithRegex = new RegExp('^' + search);
> return { projectID: startWithRegex };
> },
> 
> // Or simple exact match
> search(search) {
> return { projectID: search };
> },
> 
> ```

Just to have a cleaner example, I change the name of the SmartField and it uses the Field projectID in the get function. And it defines a **search** hook only searching the projectID of your record.

```javascript
{
  field: "project_id",
  type: "String",
  reference: "projects._id",
  isSearchable: true,
  get: function (record) {
    return record.projectID;
  },
  search(search) {
    // Example search with projectID start with the search of the user
    const startWithRegex = new RegExp('^' + search);
    return { projectID: startWithRegex };
  },
}

```

Tell me if it help.

Regards,  
Morgan
