Filter on smart field/ smart relationship

{

  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] :deciduous_tree::deciduous_tree::deciduous_tree: 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

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.

Let me know if it help !

Kind regards,
Morgan

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

I also encountered this error
[forest] :deciduous_tree::deciduous_tree::deciduous_tree: 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

{

  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


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

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.

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)

filter({ condition, where }) {
  const value = !!condition.value && condition.value;

  switch (condition.operator) {
    // Define equal operator
    case 'equal':
      return { projectID: value };

    default:
      return null;
    }
  }
},

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.

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

"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

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

Sorry, I didn’t understood it quite well. :confused:

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 ?

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 };
},

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;

    }

  },

},

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

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