Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[elasticsearch-plugin] Allow script_fields in search request body #1143

Closed
Draykee opened this issue Oct 10, 2021 · 3 comments
Closed

[elasticsearch-plugin] Allow script_fields in search request body #1143

Draykee opened this issue Oct 10, 2021 · 3 comments

Comments

@Draykee
Copy link
Contributor

Draykee commented Oct 10, 2021

Is your feature request related to a problem? Please describe.
There is currently no possibility to set script_fields to allow script evaluation for each hit.
https://www.elastic.co/guide/en/elasticsearch/reference/7.8/search-fields.html#script-fields

Describe the solution you'd like

  • Add a search config entry to return a script_fields configuration.
  • The field that contains the evaluated script value needs to be mapped to the search result
  • "_source": true, needs to be set in the request body to still include the whole index document (When using script fields, the default response will not contain the _source field but only the custom field we have defined)

Additional context
Assuming the product should receive a location via custom fields. I would like to add geo location based search and therefore I extend the SearchInput with latitude , longitude (and als distance). Here is a example of a possible configutation:

indexMappingProperties: {
     location: {
         type: 'geo_point', // contains function arcDistance
     },
},
customProductMappings: {
     location: {
         graphQlType: 'String',
         valueFn: (product: Product) => {
             const custom = product.customFields.location;
             return `${custom.latitude},${location.longitude}`;
         },
     }
},
mapQuery: (query: any, input: SearchInput, searchConfig: DeepRequired<SearchConfig>) => {
  // Dummy implementation of the geo distance search
  const distance = input.radius;
  const lat = input.latitude;
  const lon = input.longitude;
  
  if (lat && lon && distance) {
      query.bool.must = {
          match_all: {},
      };
      query.bool.filter = {
          geo_distance: {
              distance: `${distance}km`,
              location: {
                  lat,
                  lon,
              },
          },
      };
  
  }
  
  return query;
},
// The new config entry !
scriptFields: (input) => {
     // assuming SearchInput was extended with latitude and longitude
    // this script would add a 
     const lat = input.latitude;
     const lon = input.longitude;
     return {
         distance: {
             script: `doc['location'].arcDistance(${lat}, ${lon})`,
         }
     }
}

This script will add a field with the distance like this inside the ElasticSearch response:

"fields": {
  "distance": [
    103861.9371616157
  ]
}
@Draykee
Copy link
Contributor Author

Draykee commented Oct 11, 2021

I've been working on this and I'm nearly finished. I found out that createSyntheticProductIndexItem will not apply customProductMappings. This causes a script I want to apply to fail in a e2e test, because there is no value. Sure, I could no extend the script to check the field first, but I thought maybe it's also better to apply custom mappings to a synthetic product.

@michaelbromley What do you think?

customProductMappings: {
    answer: {
        graphQlType: 'Int!',
        valueFn: args => {
            return 42;
        },
    },
},
searchConfig: {
    scriptFields: {
        answerDouble: {
            graphQlType: 'Int!',
            environment: 'product',
            scriptFn: (input) => ({
                script: `doc['answer'].value * 2` // answer is not mapped for synthetic products
            })
        }
    }
}

@Izayda
Copy link
Contributor

Izayda commented Oct 11, 2021

@Draykee hi! How did you managed to extend SearchInput from config? As i understand, it is impossible now

@Draykee
Copy link
Contributor Author

Draykee commented Oct 11, 2021

@Izayda My example was just assuming that it was done. You can do it with another plugin or inside the vendure-config. Right now it's not possible - you are right.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants