> ## Documentation Index
> Fetch the complete documentation index at: https://auth0-docs-user-search.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Lucene Query Syntax and Examples for Auth0 User Search

> View Lucene query syntax details and examples for Auth0 user search version 3.

export const AuthCodeGroup = ({children, dropdown}) => {
  const [processedChildren, setProcessedChildren] = useState(children);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      unsubscribe = window.autorun(() => {
        const processChildren = node => {
          if (typeof node === "string") {
            let processedNode = node;
            for (const [key, value] of window.rootStore.variableStore.values.entries()) {
              const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
              processedNode = processedNode.replaceAll(new RegExp(escapedKey, "g"), value);
            }
            return processedNode;
          } else if (Array.isArray(node)) {
            return node.map(processChildren);
          } else if (node && node.props && node.props.children) {
            return {
              ...node,
              props: {
                ...node.props,
                children: processChildren(node.props.children)
              }
            };
          }
          return node;
        };
        setProcessedChildren(processChildren(children));
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  return <CodeGroup dropdown={dropdown}>{processedChildren}</CodeGroup>;
};

export const AuthCodeBlock = ({filename, icon, language, highlight, children}) => {
  const [displayText, setDisplayText] = useState(children);
  const [copyText, setCopyText] = useState(children);
  const wrapperRef = React.useRef(null);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      if (!window.autorun || !window.rootStore) {
        return;
      }
      unsubscribe = window.autorun(() => {
        let processedChildrenForDisplay = children;
        let processedChildrenForCopy = children;
        for (const [key, value] of window.rootStore.variableStore.values.entries()) {
          const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
          let displayValue = value;
          if (key === "{yourClientSecret}" && value !== "{yourClientSecret}") {
            displayValue = value.substring(0, 3) + "*****MASKED*****";
          }
          processedChildrenForDisplay = processedChildrenForDisplay.replaceAll(new RegExp(escapedKey, "g"), displayValue);
          processedChildrenForCopy = processedChildrenForCopy.replaceAll(new RegExp(escapedKey, "g"), value);
        }
        setDisplayText(processedChildrenForDisplay);
        setCopyText(processedChildrenForCopy);
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  useEffect(() => {
    if (!wrapperRef.current) return;
    const originalWriteText = navigator.clipboard.writeText.bind(navigator.clipboard);
    let isOverriding = false;
    const handleClick = e => {
      const button = e.target.closest('[data-testid="copy-code-button"]');
      if (!button || !wrapperRef.current.contains(button)) return;
      isOverriding = true;
      navigator.clipboard.writeText = text => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
          return originalWriteText(copyText);
        }
        return originalWriteText(text);
      };
      setTimeout(() => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
        }
      }, 100);
    };
    const wrapper = wrapperRef.current;
    wrapper.addEventListener('click', handleClick, true);
    return () => {
      wrapper.removeEventListener('click', handleClick, true);
      if (navigator.clipboard.writeText !== originalWriteText) {
        navigator.clipboard.writeText = originalWriteText;
      }
    };
  }, [copyText]);
  return <div ref={wrapperRef}>
      <CodeBlock filename={filename} icon={icon} language={language} lines highlight={highlight}>
        {displayText}
      </CodeBlock>
    </div>;
};

When [listing users](./list-and-search-users), you can filter results with search queries in Lucene query syntax.

The [Lucene query syntax reference](https://lucene.apache.org/core/2_9_4/queryparsersyntax.html) is the authoritative reference, but at a high level, the query string is parsed into a series of terms and boolean operators.

## Terms

[Terms](https://lucene.apache.org/core/2_9_4/queryparsersyntax.html#Terms) define strings to search for. Terms support fields, wildcards, and ranges.

### Fields

[Fields](https://lucene.apache.org/core/2_9_4/queryparsersyntax.html#Fields) define where to search for the given string. The [full list of user profile attributes](/docs/manage-users/user-accounts/user-profiles/user-profile-structure) indicates which fields are searchable.

* All search values are case sensitive except for search values for [normalized user profile fields](/docs/manage-users/user-accounts/user-profiles/normalized-user-profile-schema) (`email`, `name`, `given_name`, `family_name`, and `nickname`), which are case insensitive.

* You can search `app_metadata` and `user_metadata` fields with a data type of boolean, integer, double, text, object, or array.

* You cannot search metadata fields that contain an empty array, empty object, or `null` value because those values are not indexed.

* Terms without field names do not match `user_metadata`.

| Search criteria                           | Example query                           |
| ----------------------------------------- | --------------------------------------- |
| Users whose name is exactly "eugenio"     | `name:"eugenio"`                        |
| Users whose email domain is `example.com` | `email.domain:"example.com"`            |
| Users from a specific connection          | `identities.connection:"google-oauth2"` |

When searching metadata, you can search nested values using the path to the field. If the field is nested in an array, you can ignore the array level. For example, with the following `user_metadata` structure:

```json theme={null}
{
  "full_name": "Example Name",
  "display": {
    "preferredLanguage": "en",
    "fontSize": 13
  },
  "addresses":{
    "cities": [ "Paris", "Seattle" ]
  }
}
```

| Search criteria                         | Example query                                         |
| --------------------------------------- | ----------------------------------------------------- |
| Users whose full name is "Example Name" | `user_metadata.full_name:"Example Name"`              |
| Users who have set a preferred language | `q: _exists_:user_metadata.display.preferredLanguage` |
| Users whose font size is set to 13      | `q: user_metadata.display.fontSize:13`                |
| Users whose cities contain Paris        | `q: user_metadata.addresses.cities:"Paris"`           |

### Wildcards

[Wildcards](https://lucene.apache.org/core/2_9_4/queryparsersyntax.html#Wildcard%20Searches) match multiple characters using the syntax `*`.

* For suffix matching, literals must have 3 characters or more. For example, `name:*abc` is allowed, but `name:*ab` is not.

* You cannot search `user_metadata` with wildcards.

| Search criteria                      | Example query    |
| ------------------------------------ | ---------------- |
| Users whose name contains "example"  | `name:*example*` |
| Users whose email starts with "test" | `email:test*`    |

### Ranges

[Ranges](https://lucene.apache.org/core/2_9_4/queryparsersyntax.html#Range%20Searches) match values between the specified upper and lower bound.

* You cannot search `user_metadata` with ranges.

| Search criteria                             | Example query                           |
| ------------------------------------------- | --------------------------------------- |
| Users with 9 or fewer logins                | `logins_count:[* TO 10}`                |
| Users with 10 to 99 logins                  | `logins_count:[10 TO 100}`              |
| Users with 100 or more logins               | `logins_count:[100 TO *]`               |
| Users who last logged in before 2025        | `last_login:[* TO 2024-12-31]`          |
| Users whose last login was in December 2025 | `last_login:[2025-12-01 TO 2025-12-31]` |

## Boolean operators

[Boolean operators](https://lucene.apache.org/core/2_9_4/queryparsersyntax.html#Boolean%20operators) logically combine terms. Boolean operators work on all normalized user profile fields and root metadata fields.

| Search criteria                                           | Example query                                         |
| --------------------------------------------------------- | ----------------------------------------------------- |
| Users whose name is exactly "example name" or "test user" | `name:("example name" OR "test user")`                |
| Users without a verified email                            | `NOT _exists_:email_verified OR email_verified:false` |
| Users who have never logged in                            | `NOT _exists_:logins_count OR logins_count:0`         |
