> ## Documentation Index
> Fetch the complete documentation index at: https://doc.lucidworks.com/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript Query Stage

export const schema = {
  "type": "object",
  "title": "JavaScript",
  "description": "Manipulate the request using JavaScript",
  "required": ["script"],
  "properties": {
    "skip": {
      "type": "boolean",
      "title": "Skip This Stage",
      "description": "Set to true to skip this stage.",
      "default": false,
      "hints": ["advanced"]
    },
    "label": {
      "type": "string",
      "title": "Label",
      "description": "A unique label for this stage.",
      "hints": ["advanced"],
      "maxLength": 255
    },
    "condition": {
      "type": "string",
      "title": "Condition",
      "description": "Define a conditional script that must result in true or false. This can be used to determine if the stage should process or not.",
      "hints": ["code", "code/javascript", "advanced"]
    },
    "script": {
      "type": "string",
      "title": "Script Body",
      "description": "One context variable 'request' is visible to the script.",
      "hints": ["lengthy", "code", "code/javascript"]
    },
    "shareState": {
      "type": "boolean",
      "title": "Share state",
      "description": "Causes all instances of this stage to share state. Enabling this will increase performance, but can lead to unexpected behavior if any variables are declared globally. This is safe to use if you declare all variables explicitly using 'var'.",
      "default": false
    }
  },
  "category": "Advanced",
  "categoryPriority": 2,
  "unsafe": true
};

export const SchemaParamFields = ({schema}) => {
  const sanitize = str => {
    if (typeof str !== "string") return str;
    return str.replace(/^"(.*)"$/s, "$1").replace(/\\/g, "").replace(/"/g, "'");
  };
  const formatDescription = str => {
    const s = sanitize(str);
    return (/[.!?]\)*$/).test(s) ? s : `${s}.`;
  };
  const {description, properties = {}, required: requiredProps = []} = schema;
  const visibleProps = useMemo(() => Object.entries(properties).filter(([, prop]) => !prop.hints?.includes("hidden")), [properties]);
  return <div>
      {description && <p>{formatDescription(description)}</p>}

      {visibleProps.map(([name, prop]) => {
    const isRequired = requiredProps.includes(name);
    const hasDefault = prop.default !== undefined;
    const rawDefault = prop.default;
    const isComplexDefault = hasDefault && (typeof rawDefault === "object" || typeof rawDefault === "string" && (rawDefault.length > 20 || rawDefault.includes('"')));
    const fieldProps = {
      key: name,
      body: prop.title || name,
      type: prop.type,
      ...prop.title && ({
        post: [<><span className="text-stone-400 dark:text-stone-500">API property: </span>{name}</>]
      }),
      ...isRequired && ({
        required: true
      }),
      ...!isComplexDefault && hasDefault ? {
        default: sanitize(String(rawDefault))
      } : {}
    };
    const isObject = prop.type === "object" && prop.properties;
    const isArrayOfObjects = prop.type === "array" && prop.items?.type === "object" && prop.items.properties;
    return <ParamField {...fieldProps}>
            {prop.description && <p>{formatDescription(prop.description)}</p>}

            {isComplexDefault && <div className="flex">
                <p>
                  <strong>Default:</strong>
                </p>
                <pre className="!my-0">
                  <code>
                    {JSON.stringify(rawDefault, null, 2)}
                  </code>
                </pre>
              </div>}

            {isArrayOfObjects && <div className="flex">
              <p>
                <strong>Object attributes:</strong>
              </p>
              <pre className="!my-0">
                <code>
                  {'{\n'}
                  {Object.entries(prop.items.properties).map(([iname, iprop]) => <>
                      {`  ${iname}`}
                      {prop.items?.required?.includes(iname) && <span style={{
      color: 'red'
    }}> required</span>}
                      {`: {\n    display name: ${sanitize(iprop.title || '')}\n    type: ${iprop.type}\n  }\n`}
                    </>)}
                  {'}'}
                </code>
              </pre>
              </div>}

            {isObject && <Expandable title="properties">
                <SchemaParamFields schema={{
      properties: prop.properties,
      required: prop.required
    }} />
              </Expandable>}
          </ParamField>;
  })}
    </div>;
};

export const LwTemplate = ({title = "Key questions to get you started", icon = "sparkles", cta = "Powered by Agent Studio", linkHref = "https://lucidworks.com/demo/?utm_source=docs&utm_medium=referral&utm_campaign=docs_cta_ai"}) => {
  const [isLoaded, setIsLoaded] = useState(false);
  useEffect(() => {
    const timer = setTimeout(() => {
      setIsLoaded(true);
    }, 500);
    return () => clearTimeout(timer);
  }, []);
  return <div className="lw-template-container">
      <Card title={title} icon={icon}>
        {isLoaded && <span dangerouslySetInnerHTML={{
    __html: `<lw-template id="a029c1a9-28be-427e-b0e1-5d918920246a"></lw-template
            >`
  }} />}
        <Link href={linkHref} className="agent-studio-link text-left text-gray-600 gap-2 dark:text-gray-400 text-sm font-medium flex flex-row items-center hover:text-primary dark:hover:text-primary-light group-hover:text-primary group-hover:dark:text-primary-light">Powered by Lucidworks Agent Studio</Link>
      </Card>
    </div>;
};

[localhost link]: http://localhost:3000/docs/4/fusion-server/reference/pipeline-stages/query/javascript-query-stage

[mintlify link]: https://doc.lucidworks.com/docs/4/fusion-server/reference/pipeline-stages/query/javascript-query-stage

[old doc.lw link]: https://doc.lucidworks.com/fusion-server/4.2/89cjix

The JavaScript Query stage allows you to write custom processing logic using JavaScript to manipulate search requests and responses. The first time that the pipeline is run, Fusion compiles the JavaScript program into Java bytecode using the JDK’s JavaScript engine.

The JavaScript Query stage allows you to run JavaScript functions over search requests and responses by manipulating variables called "request" and "response" which are Request objects and Response objects, respectively.

<Warning>
  If you are running more than 50 JavaScript query pipelines stages, you might experience performance issues when refreshing a query pipeline.
</Warning>

<LwTemplate />

## JavaScript Stages Variables and Parameters

[JavaScript](http://en.wikipedia.org/wiki/JavaScript) is a lightweight scripting language.
The JavaScript in a JavaScript stage is standard [ECMAScript](http://en.wikipedia.org/wiki/ECMAScript).
What a JavaScript program can do depends on the container in which it runs.
For a JavaScript Query stage, the container is a Fusion query pipeline.
The following global pipeline variables are available:

| Name                      | Type                                                                                                                                                     | Description                                                                                                                                                                                                                                                                              |
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `request`                 | [Request](https://javadoc.lucidworks.com/fusion-pipeline-javadocs/4.2/com/lucidworks/apollo/pipeline/query/Request.html)                                 | The Solr query information.                                                                                                                                                                                                                                                              |
| `response`                | [Response](https://javadoc.lucidworks.com/fusion-pipeline-javadocs/4.2/com/lucidworks/apollo/pipeline/query/Response.html)                               | The Solr response information.                                                                                                                                                                                                                                                           |
| `ctx`                     | [Context](https://javadoc.lucidworks.com/fusion-pipeline-javadocs/4.2/com/lucidworks/apollo/pipeline/Context.html)                                       | A reference to the container which holds a map over the pipeline properties. Used to update or modify this information for downstream pipeline stages.                                                                                                                                   |
| `collection`              | String                                                                                                                                                   | The name of the Fusion collection being indexed or queried.                                                                                                                                                                                                                              |
| `solrServer`              | [BufferingSolrServer](https://javadoc.lucidworks.com/fusion-pipeline-javadocs/4.2/com/lucidworks/apollo/component/BufferingSolrServer)                   | The Solr server instance that manages the pipeline’s default Fusion collection. All indexing and query requests are done by calls to methods on this object. See [SolrClient](https://lucene.apache.org/solr/5_2_1/solr-solrj/org/apache/solr/client/solrj/SolrClient.html) for details. |
| `solrServerFactory`       | [SolrClientFactory](https://javadoc.lucidworks.com/fusion-pipeline-javadocs/4.2/com/lucidworks/apollo/component/SolrClientFactory.html)                  | The SolrCluster server used for lookups by collection name which returns a Solr server instance for a that collection. For example:  `var productsSolr = solrServerFactory.getSolrServer("products");`.                                                                                  |
| `QueryRequestAndResponse` | [QueryRequestAndResponse](https://javadoc.lucidworks.com/fusion-pipeline-javadocs/4.2/com/lucidworks/apollo/pipeline/query/QueryRequestAndResponse.html) | Returns list of info as a string.                                                                                                                                                                                                                                                        |

### Syntax Variants

JavaScript stages are written using ***function syntax***, which passes variables as function parameters.

#### Function Syntax

```javascript wrap  theme={"dark"}
function(request,response) {
   request.addParam("foo", "bar");
}
```

<Tip>
  **Important**

  *Function syntax* is used for the examples in this document.
</Tip>

### Global variable `logger`

The global variable named `logger` writes messages to the log file of the server running the pipeline.
This variable is truly global and does not need to be declared as part of the function parameter list.

There are 5 methods available, which each take either a single argument (the string message to log) or two arguments (the string message and an exception to log).
The five methods are, "debug", "info", "warn", and "error".

## Configuration

<Tip>
  When entering configuration values in the UI, use *unescaped* characters, such as `\t` for the tab character. When entering configuration values in the API, use *escaped* characters, such as `\\t` for the tab character.
</Tip>

<SchemaParamFields schema={schema} />
