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

# Full-text Index

> FalkorDB provides full-text indices through procedure calls and DDL syntax.

FalkorDB leverages the indexing capabilities of [RediSearch](https://redis.io/docs/interact/search-and-query/) to provide full-text indices through procedure calls and DDL syntax.

## Creating a full-text index for a node label

### Using procedure syntax

To construct a full-text index on the `title` property of all nodes with label `Movie`, use the syntax:

<CodeGroup>
  ```python Python theme={null}
  graph.query("CALL db.idx.fulltext.createNodeIndex('Movie', 'title')")
  ```

  ```javascript JavaScript theme={null}
  await graph.query("CALL db.idx.fulltext.createNodeIndex('Movie', 'title')");
  ```

  ```java Java theme={null}
  graph.query("CALL db.idx.fulltext.createNodeIndex('Movie', 'title')");
  ```

  ```rust Rust theme={null}
  graph.query("CALL db.idx.fulltext.createNodeIndex('Movie', 'title')").execute().await?;
  ```

  ```bash Shell theme={null}
  GRAPH.QUERY DEMO_GRAPH "CALL db.idx.fulltext.createNodeIndex('Movie', 'title')"
  ```
</CodeGroup>

More properties can be added to this index by adding their names to the above set of arguments, or using this syntax again with the additional names.

<CodeGroup>
  ```python Python theme={null}
  graph.query("CALL db.idx.fulltext.createNodeIndex('Person', 'firstName', 'lastName')")
  ```

  ```javascript JavaScript theme={null}
  await graph.query("CALL db.idx.fulltext.createNodeIndex('Person', 'firstName', 'lastName')");
  ```

  ```java Java theme={null}
  graph.query("CALL db.idx.fulltext.createNodeIndex('Person', 'firstName', 'lastName')");
  ```

  ```rust Rust theme={null}
  graph.query("CALL db.idx.fulltext.createNodeIndex('Person', 'firstName', 'lastName')").execute().await?;
  ```

  ```bash Shell theme={null}
  GRAPH.QUERY DEMO_GRAPH "CALL db.idx.fulltext.createNodeIndex('Person', 'firstName', 'lastName')"
  ```
</CodeGroup>

Index configuration options:

1. Language - Define which language to use for stemming text, which is adding the base form of a word to the index. This allows the query for "going" to also return results for "go" and "gone", for example.
2. Stopwords - These are words that are usually so common that they do not add much information to search, but take up a lot of space and CPU time in the index.

To construct a full-text index on the `title` property using `German` language and using custom stopwords of all nodes with label `Movie`, use the syntax:

<CodeGroup>
  ```python Python theme={null}
  graph.query("CALL db.idx.fulltext.createNodeIndex({ label: 'Movie', language: 'German', stopwords: ['a', 'ab'] }, 'title')")
  ```

  ```javascript JavaScript theme={null}
  await graph.query("CALL db.idx.fulltext.createNodeIndex({ label: 'Movie', language: 'German', stopwords: ['a', 'ab'] }, 'title')");
  ```

  ```java Java theme={null}
  graph.query("CALL db.idx.fulltext.createNodeIndex({ label: 'Movie', language: 'German', stopwords: ['a', 'ab'] }, 'title')");
  ```

  ```rust Rust theme={null}
  graph.query("CALL db.idx.fulltext.createNodeIndex({ label: 'Movie', language: 'German', stopwords: ['a', 'ab'] }, 'title')").execute().await?;
  ```

  ```bash Shell theme={null}
  GRAPH.QUERY DEMO_GRAPH "CALL db.idx.fulltext.createNodeIndex({ label: 'Movie', language: 'German', stopwords: ['a', 'ab'] }, 'title')"
  ```
</CodeGroup>

Additional field configuration options:

1. Weight - The importance of the text in the field
2. Nostem - Skip stemming when indexing text
3. Phonetic - Enable phonetic search on the text

To construct a full-text index on the `title` property with phonetic search of all nodes with label `Movie`, use the syntax:

<CodeGroup>
  ```python Python theme={null}
  graph.query("CALL db.idx.fulltext.createNodeIndex('Movie', {field: 'title', phonetic: 'dm:en'})")
  ```

  ```javascript JavaScript theme={null}
  await graph.query("CALL db.idx.fulltext.createNodeIndex('Movie', {field: 'title', phonetic: 'dm:en'})");
  ```

  ```java Java theme={null}
  graph.query("CALL db.idx.fulltext.createNodeIndex('Movie', {field: 'title', phonetic: 'dm:en'})");
  ```

  ```rust Rust theme={null}
  graph.query("CALL db.idx.fulltext.createNodeIndex('Movie', {field: 'title', phonetic: 'dm:en'})").execute().await?;
  ```

  ```bash Shell theme={null}
  GRAPH.QUERY DEMO_GRAPH "CALL db.idx.fulltext.createNodeIndex('Movie', {field: 'title', phonetic: 'dm:en'})"
  ```
</CodeGroup>

### Using DDL syntax

Full-text indexes for node labels can also be created using DDL syntax:

<CodeGroup>
  ```python Python theme={null}
  graph.query("CREATE FULLTEXT INDEX FOR (n:Movie) ON (n.title)")
  ```

  ```javascript JavaScript theme={null}
  await graph.query("CREATE FULLTEXT INDEX FOR (n:Movie) ON (n.title)");
  ```

  ```java Java theme={null}
  graph.query("CREATE FULLTEXT INDEX FOR (n:Movie) ON (n.title)");
  ```

  ```rust Rust theme={null}
  graph.query("CREATE FULLTEXT INDEX FOR (n:Movie) ON (n.title)").execute().await?;
  ```

  ```bash Shell theme={null}
  GRAPH.QUERY DEMO_GRAPH "CREATE FULLTEXT INDEX FOR (n:Movie) ON (n.title)"
  ```
</CodeGroup>

An `OPTIONS` block can be provided to specify additional configuration such as language and stopwords:

<CodeGroup>
  ```python Python theme={null}
  graph.query("CREATE FULLTEXT INDEX FOR (n:Movie) ON (n.title) OPTIONS { language: 'German', stopwords: ['a', 'ab'] }")
  ```

  ```javascript JavaScript theme={null}
  await graph.query("CREATE FULLTEXT INDEX FOR (n:Movie) ON (n.title) OPTIONS { language: 'German', stopwords: ['a', 'ab'] }");
  ```

  ```java Java theme={null}
  graph.query("CREATE FULLTEXT INDEX FOR (n:Movie) ON (n.title) OPTIONS { language: 'German', stopwords: ['a', 'ab'] }");
  ```

  ```rust Rust theme={null}
  graph.query("CREATE FULLTEXT INDEX FOR (n:Movie) ON (n.title) OPTIONS { language: 'German', stopwords: ['a', 'ab'] }").execute().await?;
  ```

  ```bash Shell theme={null}
  GRAPH.QUERY DEMO_GRAPH "CREATE FULLTEXT INDEX FOR (n:Movie) ON (n.title) OPTIONS { language: 'German', stopwords: ['a', 'ab'] }"
  ```
</CodeGroup>

## Query Syntax and Features

FalkorDB uses [RediSearch query syntax](https://redis.io/docs/latest/develop/ai/search-and-query/advanced-concepts/query_syntax/) which provides powerful search capabilities including fuzzy matching, prefix matching, and tokenization.

### Tokenization

When text is indexed, it is automatically tokenized (split into words). By default, text is split on whitespace and punctuation. This allows you to search for individual words within larger text fields.

For example, if you index a `title` property containing "The Lord of the Rings", you can search for any of the individual words like "Lord" or "Rings".

### Prefix Matching

Prefix matching allows you to search for words that start with a specific prefix using the `*` wildcard. This is useful for autocomplete functionality or when you want to match word variations.

<CodeGroup>
  ```python Python theme={null}
  # Find all movies with titles containing words starting with "Jun"
  result = graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Jun*') YIELD node RETURN node.title")
  for record in result:
      print(record["node.title"])
  # This would match "Jungle", "June", "Junior", etc.
  ```

  ```javascript JavaScript theme={null}
  // Find all movies with titles containing words starting with "Jun"
  const result = await graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Jun*') YIELD node RETURN node.title");
  for (const record of result.data) {
      console.log(record["node.title"]);
  }
  // This would match "Jungle", "June", "Junior", etc.
  ```

  ```java Java theme={null}
  // Find all movies with titles containing words starting with "Jun"
  ResultSet result = graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Jun*') YIELD node RETURN node.title");
  for (Record record : result) {
      System.out.println(record.get("node.title"));
  }
  // This would match "Jungle", "June", "Junior", etc.
  ```

  ```rust Rust theme={null}
  // Find all movies with titles containing words starting with "Jun"
  let result = graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Jun*') YIELD node RETURN node.title").execute().await?;
  for record in result.data() {
      println!("{}", record["node.title"]);
  }
  // This would match "Jungle", "June", "Junior", etc.
  ```

  ```bash Shell theme={null}
  # Find all movies with titles containing words starting with "Jun"
  GRAPH.QUERY DEMO_GRAPH "CALL db.idx.fulltext.queryNodes('Movie', 'Jun*') YIELD node RETURN node.title"
  # This would match "Jungle", "June", "Junior", etc.
  ```
</CodeGroup>

**Note:** Prefix matching only works at the end of a word (e.g., `Jun*`). The wildcard must appear at the end of the search term.

### Fuzzy Matching

Fuzzy matching allows you to find words that are similar to your search term, accounting for typos and spelling variations. Use the `%` symbol followed by the Levenshtein distance (number of character changes allowed).

<CodeGroup>
  ```python Python theme={null}
  # Find movies with titles containing words similar to "Jangle" (allowing 1 character difference)
  result = graph.query("CALL db.idx.fulltext.queryNodes('Movie', '%Jangle%1') YIELD node RETURN node.title")
  for record in result:
      print(record["node.title"])
  # This would match "Jungle" (1 character different)

  # Allow up to 2 character differences
  result = graph.query("CALL db.idx.fulltext.queryNodes('Movie', '%Jngle%2') YIELD node RETURN node.title")
  # This would also match "Jungle" (1 character missing)
  ```

  ```javascript JavaScript theme={null}
  // Find movies with titles containing words similar to "Jangle" (allowing 1 character difference)
  const result = await graph.query("CALL db.idx.fulltext.queryNodes('Movie', '%Jangle%1') YIELD node RETURN node.title");
  for (const record of result.data) {
      console.log(record["node.title"]);
  }
  // This would match "Jungle" (1 character different)

  // Allow up to 2 character differences
  const result2 = await graph.query("CALL db.idx.fulltext.queryNodes('Movie', '%Jngle%2') YIELD node RETURN node.title");
  // This would also match "Jungle" (1 character missing)
  ```

  ```java Java theme={null}
  // Find movies with titles containing words similar to "Jangle" (allowing 1 character difference)
  ResultSet result = graph.query("CALL db.idx.fulltext.queryNodes('Movie', '%Jangle%1') YIELD node RETURN node.title");
  for (Record record : result) {
      System.out.println(record.get("node.title"));
  }
  // This would match "Jungle" (1 character different)

  // Allow up to 2 character differences
  ResultSet result2 = graph.query("CALL db.idx.fulltext.queryNodes('Movie', '%Jngle%2') YIELD node RETURN node.title");
  // This would also match "Jungle" (1 character missing)
  ```

  ```rust Rust theme={null}
  // Find movies with titles containing words similar to "Jangle" (allowing 1 character difference)
  let result = graph.query("CALL db.idx.fulltext.queryNodes('Movie', '%Jangle%1') YIELD node RETURN node.title").execute().await?;
  for record in result.data() {
      println!("{}", record["node.title"]);
  }
  // This would match "Jungle" (1 character different)

  // Allow up to 2 character differences
  let result2 = graph.query("CALL db.idx.fulltext.queryNodes('Movie', '%Jngle%2') YIELD node RETURN node.title").execute().await?;
  // This would also match "Jungle" (1 character missing)
  ```

  ```bash Shell theme={null}
  # Find movies with titles containing words similar to "Jangle" (allowing 1 character difference)
  GRAPH.QUERY DEMO_GRAPH "CALL db.idx.fulltext.queryNodes('Movie', '%Jangle%1') YIELD node RETURN node.title"
  # This would match "Jungle" (1 character different)

  # Allow up to 2 character differences
  GRAPH.QUERY DEMO_GRAPH "CALL db.idx.fulltext.queryNodes('Movie', '%Jngle%2') YIELD node RETURN node.title"
  # This would also match "Jungle" (1 character missing)
  ```
</CodeGroup>

**Fuzzy matching syntax:** `%term%distance` where:

* `term` is the word to match
* `distance` is the maximum Levenshtein distance (1-3, default is 1 if not specified)

**Note:** Fuzzy matching is computationally more expensive than exact or prefix matching, so use it judiciously on large datasets.

### Combining Query Features

You can combine multiple search terms using boolean operators:

* `AND` (or space): All terms must match
* `OR` (`|`): At least one term must match
* `NOT` (`-`): Term must not be present

<CodeGroup>
  ```python Python theme={null}
  # Find movies with "Jungle" AND "Book" in the title
  result = graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Jungle Book') YIELD node RETURN node.title")

  # Find movies with "Jungle" OR "Forest" in the title
  result = graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Jungle|Forest') YIELD node RETURN node.title")

  # Find movies with "Book" but NOT "Jungle"
  result = graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Book -Jungle') YIELD node RETURN node.title")

  # Combine prefix and fuzzy matching
  result = graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Jun*|%Forst%1') YIELD node RETURN node.title")
  ```

  ```javascript JavaScript theme={null}
  // Find movies with "Jungle" AND "Book" in the title
  const result = await graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Jungle Book') YIELD node RETURN node.title");

  // Find movies with "Jungle" OR "Forest" in the title
  const result2 = await graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Jungle|Forest') YIELD node RETURN node.title");

  // Find movies with "Book" but NOT "Jungle"
  const result3 = await graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Book -Jungle') YIELD node RETURN node.title");

  // Combine prefix and fuzzy matching
  const result4 = await graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Jun*|%Forst%1') YIELD node RETURN node.title");
  ```

  ```java Java theme={null}
  // Find movies with "Jungle" AND "Book" in the title
  ResultSet result = graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Jungle Book') YIELD node RETURN node.title");

  // Find movies with "Jungle" OR "Forest" in the title
  ResultSet result2 = graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Jungle|Forest') YIELD node RETURN node.title");

  // Find movies with "Book" but NOT "Jungle"
  ResultSet result3 = graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Book -Jungle') YIELD node RETURN node.title");

  // Combine prefix and fuzzy matching
  ResultSet result4 = graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Jun*|%Forst%1') YIELD node RETURN node.title");
  ```

  ```rust Rust theme={null}
  // Find movies with "Jungle" AND "Book" in the title
  let result = graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Jungle Book') YIELD node RETURN node.title").execute().await?;

  // Find movies with "Jungle" OR "Forest" in the title
  let result2 = graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Jungle|Forest') YIELD node RETURN node.title").execute().await?;

  // Find movies with "Book" but NOT "Jungle"
  let result3 = graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Book -Jungle') YIELD node RETURN node.title").execute().await?;

  // Combine prefix and fuzzy matching
  let result4 = graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Jun*|%Forst%1') YIELD node RETURN node.title").execute().await?;
  ```

  ```bash Shell theme={null}
  # Find movies with "Jungle" AND "Book" in the title
  GRAPH.QUERY DEMO_GRAPH "CALL db.idx.fulltext.queryNodes('Movie', 'Jungle Book') YIELD node RETURN node.title"

  # Find movies with "Jungle" OR "Forest" in the title
  GRAPH.QUERY DEMO_GRAPH "CALL db.idx.fulltext.queryNodes('Movie', 'Jungle|Forest') YIELD node RETURN node.title"

  # Find movies with "Book" but NOT "Jungle"
  GRAPH.QUERY DEMO_GRAPH "CALL db.idx.fulltext.queryNodes('Movie', 'Book -Jungle') YIELD node RETURN node.title"

  # Combine prefix and fuzzy matching: Find "Jun*" OR words similar to "Forst"
  GRAPH.QUERY DEMO_GRAPH "CALL db.idx.fulltext.queryNodes('Movie', 'Jun*|%Forst%1') YIELD node RETURN node.title"
  ```
</CodeGroup>

For more advanced query syntax features, see the [RediSearch query syntax documentation](https://redis.io/docs/latest/develop/ai/search-and-query/advanced-concepts/query_syntax/).

## Utilizing a full-text index for a node label

An index can be invoked to match any whole words contained within:

<CodeGroup>
  ```python Python theme={null}
  result = graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Book') YIELD node RETURN node.title")
  for record in result:
      print(record["node.title"])
  # Output:
  # The Jungle Book
  # The Book of Life
  ```

  ```javascript JavaScript theme={null}
  const result = await graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Book') YIELD node RETURN node.title");
  for (const record of result.data) {
      console.log(record["node.title"]);
  }
  // Output:
  // The Jungle Book
  // The Book of Life
  ```

  ```java Java theme={null}
  ResultSet result = graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Book') YIELD node RETURN node.title");
  for (Record record : result) {
      System.out.println(record.get("node.title"));
  }
  // Output:
  // The Jungle Book
  // The Book of Life
  ```

  ```rust Rust theme={null}
  let result = graph.query("CALL db.idx.fulltext.queryNodes('Movie', 'Book') YIELD node RETURN node.title").execute().await?;
  for record in result.data() {
      println!("{}", record["node.title"]);
  }
  // Output:
  // The Jungle Book
  // The Book of Life
  ```

  ```bash Shell theme={null}
  GRAPH.QUERY DEMO_GRAPH
  "CALL db.idx.fulltext.queryNodes('Movie', 'Book') YIELD node RETURN node.title"
  1) 1) "node.title"
  2) 1) 1) "The Jungle Book"
     2) 1) "The Book of Life"
  3) 1) "Query internal execution time: 0.927409 milliseconds"
  ```
</CodeGroup>

This CALL clause can be interleaved with other Cypher clauses to perform more elaborate manipulations:

```sh theme={null}
GRAPH.QUERY DEMO_GRAPH
"CALL db.idx.fulltext.queryNodes('Movie', 'Book') YIELD node AS m
WHERE m.genre = 'Adventure'
RETURN m ORDER BY m.rating"
1) 1) "m"
2) 1) 1) 1) 1) "id"
            2) (integer) 1168
         2) 1) "labels"
            2) 1) "Movie"
         3) 1) "properties"
            2) 1) 1) "genre"
                  2) "Adventure"
               2) 1) "rating"
                  2) "7.6"
               3) 1) "votes"
                  2) (integer) 151342
               4) 1) "year"
                  2) (integer) 2016
               5) 1) "title"
                  2) "The Jungle Book"
3) 1) "Query internal execution time: 0.226914 milliseconds"
```

In addition to yielding matching nodes, full-text index scans will return the score of each node. This is the [TF-IDF](https://redis.io/docs/interact/search-and-query/advanced-concepts/scoring/#tfidf-default) score of the node, which is informed by how many times the search terms appear in the node and how closely grouped they are. This can be observed in the example:

```sh theme={null}
GRAPH.QUERY DEMO_GRAPH
"CALL db.idx.fulltext.queryNodes('Node', 'hello world') YIELD node, score RETURN score, node.val"
1) 1) "score"
   2) "node.val"
2) 1) 1) "2"
      2) "hello world"
   2) 1) "1"
      2) "hello to a different world"
3) 1) "Cached execution: 1"
   2) "Query internal execution time: 0.335401 milliseconds"
```

## Deleting a full-text index for a node label

### Using procedure syntax

For a node label, the procedure syntax drops **all** full-text indexed properties for the given label:

<CodeGroup>
  ```python Python theme={null}
  graph.query("CALL db.idx.fulltext.drop('Movie')")
  ```

  ```javascript JavaScript theme={null}
  await graph.query("CALL db.idx.fulltext.drop('Movie')");
  ```

  ```java Java theme={null}
  graph.query("CALL db.idx.fulltext.drop('Movie')");
  ```

  ```rust Rust theme={null}
  graph.query("CALL db.idx.fulltext.drop('Movie')").execute().await?;
  ```

  ```bash Shell theme={null}
  GRAPH.QUERY DEMO_GRAPH "CALL db.idx.fulltext.drop('Movie')"
  ```
</CodeGroup>

### Using DDL syntax

Full-text indexes for node labels can also be dropped using DDL syntax. Unlike the procedure syntax above, the DDL form drops only the **specific property** index:

<CodeGroup>
  ```python Python theme={null}
  graph.query("DROP FULLTEXT INDEX FOR (n:Movie) ON (n.title)")
  ```

  ```javascript JavaScript theme={null}
  await graph.query("DROP FULLTEXT INDEX FOR (n:Movie) ON (n.title)");
  ```

  ```java Java theme={null}
  graph.query("DROP FULLTEXT INDEX FOR (n:Movie) ON (n.title)");
  ```

  ```rust Rust theme={null}
  graph.query("DROP FULLTEXT INDEX FOR (n:Movie) ON (n.title)").execute().await?;
  ```

  ```bash Shell theme={null}
  GRAPH.QUERY DEMO_GRAPH "DROP FULLTEXT INDEX FOR (n:Movie) ON (n.title)"
  ```
</CodeGroup>

## Creating Full-Text indexing for Relation Labels

To create a full-text index on the name property of all relations with the label Manager and enable phonetic search, use the following syntax:

<CodeGroup>
  ```python Python theme={null}
  graph.query("CREATE FULLTEXT INDEX FOR ()-[m:Manager]-() on (m.name)")
  ```

  ```javascript JavaScript theme={null}
  await graph.query("CREATE FULLTEXT INDEX FOR ()-[m:Manager]-() on (m.name)");
  ```

  ```java Java theme={null}
  graph.query("CREATE FULLTEXT INDEX FOR ()-[m:Manager]-() on (m.name)");
  ```

  ```rust Rust theme={null}
  graph.query("CREATE FULLTEXT INDEX FOR ()-[m:Manager]-() on (m.name)").execute().await?;
  ```

  ```bash Shell theme={null}
  GRAPH.QUERY DEMO_GRAPH "CREATE FULLTEXT INDEX FOR ()-[m:Manager]-() on (m.name)"
  ```
</CodeGroup>

## Querying with a Full-Text Index

To search for specific words within the indexed relations, use:

<CodeGroup>
  ```python Python theme={null}
  result = graph.query("CALL db.idx.fulltext.queryRelationships('Manager', 'Charlie Munger') YIELD relationship RETURN relationship.name")
  ```

  ```javascript JavaScript theme={null}
  const result = await graph.query("CALL db.idx.fulltext.queryRelationships('Manager', 'Charlie Munger') YIELD relationship RETURN relationship.name");
  ```

  ```java Java theme={null}
  ResultSet result = graph.query("CALL db.idx.fulltext.queryRelationships('Manager', 'Charlie Munger') YIELD relationship RETURN relationship.name");
  ```

  ```rust Rust theme={null}
  let result = graph.query("CALL db.idx.fulltext.queryRelationships('Manager', 'Charlie Munger') YIELD relationship RETURN relationship.name").execute().await?;
  ```

  ```bash Shell theme={null}
  GRAPH.QUERY DEMO_GRAPH
  "CALL db.idx.fulltext.queryRelationships('Manager', 'Charlie Munger') YIELD relationship RETURN relationship.name"
  ```
</CodeGroup>

## Deleting a Full-Text Index

To delete the full-text index for a specific relation label, use:

<CodeGroup>
  ```python Python theme={null}
  graph.query("DROP FULLTEXT INDEX FOR ()-[m:Manager]-() ON (m.name)")
  ```

  ```javascript JavaScript theme={null}
  await graph.query("DROP FULLTEXT INDEX FOR ()-[m:Manager]-() ON (m.name)");
  ```

  ```java Java theme={null}
  graph.query("DROP FULLTEXT INDEX FOR ()-[m:Manager]-() ON (m.name)");
  ```

  ```rust Rust theme={null}
  graph.query("DROP FULLTEXT INDEX FOR ()-[m:Manager]-() ON (m.name)").execute().await?;
  ```

  ```bash Shell theme={null}
  GRAPH.QUERY DEMO_GRAPH "DROP FULLTEXT INDEX FOR ()-[m:Manager]-() ON (m.name)"
  ```
</CodeGroup>

## Index Management

### Listing Full-text Indexes

To view all indexes (including full-text) in your graph, use:

```cypher theme={null}
CALL db.indexes()
```

This returns information about all indexes, with full-text indexes marked with type `FULLTEXT`.

## Performance Tradeoffs and Best Practices

### When to Use Full-text Indexes

Full-text indexes are ideal for:

* **Text-heavy search**: Searching within large text fields like descriptions, articles, or comments
* **Partial word matching**: When users might not know the exact text
* **Fuzzy search**: Handling typos and spelling variations
* **Multi-word queries**: Searching for multiple terms with boolean logic

### When NOT to Use Full-text Indexes

Full-text indexes are not optimal for:

* **Exact numeric filtering**: Use range indexes instead for numeric comparisons
* **Exact-match queries**: Range indexes are more efficient for exact property matches
* **Small or structured data**: For short, well-defined strings, range indexes may be sufficient

### Performance Considerations

**Benefits:**

* Enables sophisticated text search capabilities (fuzzy, prefix, phonetic)
* Supports stemming and language-specific optimizations
* Returns relevance scores (TF-IDF) for ranking results

**Costs:**

* **Write overhead**: Text must be tokenized and indexed on write
* **Storage**: Requires more space than range indexes due to tokenization and inverted indices
* **Configuration complexity**: Language, stopwords, and stemming settings affect results
* **Query performance**: Fuzzy matching is more expensive than exact matching

**Recommendations:**

* Choose the correct language setting for proper stemming
* Configure appropriate stopwords for your use case
* Use prefix matching (`*`) for autocomplete rather than full fuzzy search when possible
* Test query performance with realistic data volumes
* Consider the tradeoff between index configurability and query performance

### Configuration Best Practices

**Language Selection:**

* Wrong language settings can produce poor stemming results
* Example: Searching "running" with English stemming finds "run", but German stemming won't

**Stopwords:**

* Default stopwords are optimized for general text
* Customize stopwords for domain-specific applications (e.g., legal, medical, technical documents)
* Too many stopwords can hurt precision; too few increase index size

**Phonetic Search:**

* Useful for name searches and when spelling variations are common
* Increases index size and query time
* Double Metaphone (`dm:en`) is recommended for English

## Verifying Full-text Index Usage

Use `GRAPH.EXPLAIN` to verify that full-text queries use the index:

<CodeGroup>
  ```python Python theme={null}
  # Check if full-text index is used
  result = graph.explain("CALL db.idx.fulltext.queryNodes('Movie', 'Book') YIELD node RETURN node")
  print(result)
  # Output shows: ProcedureCall | db.idx.fulltext.queryNodes
  ```

  ```javascript JavaScript theme={null}
  // Check if full-text index is used
  const result = await graph.explain("CALL db.idx.fulltext.queryNodes('Movie', 'Book') YIELD node RETURN node");
  console.log(result);
  // Output shows: ProcedureCall | db.idx.fulltext.queryNodes
  ```

  ```java Java theme={null}
  // Check if full-text index is used
  String result = graph.explain("CALL db.idx.fulltext.queryNodes('Movie', 'Book') YIELD node RETURN node");
  System.out.println(result);
  // Output shows: ProcedureCall | db.idx.fulltext.queryNodes
  ```

  ```rust Rust theme={null}
  // Check if full-text index is used
  let result = graph.explain("CALL db.idx.fulltext.queryNodes('Movie', 'Book') YIELD node RETURN node").execute().await?;
  println!("{}", result);
  // Output shows: ProcedureCall | db.idx.fulltext.queryNodes
  ```

  ```bash Shell theme={null}
  # Check if full-text index is used
  GRAPH.EXPLAIN DEMO_GRAPH "CALL db.idx.fulltext.queryNodes('Movie', 'Book') YIELD node RETURN node"
  # Output shows: ProcedureCall | db.idx.fulltext.queryNodes
  ```
</CodeGroup>

## Frequently Asked Questions

<AccordionGroup>
  <Accordion title="How do I create a full-text index?">
    Use the procedure `CALL db.idx.fulltext.createNodeIndex('Label', 'property1', 'property2')`. You can index one or more properties on a given label.
  </Accordion>

  <Accordion title="How do I query a full-text index?">
    Use `CALL db.idx.fulltext.queryNodes('Label', 'search term') YIELD node, score`. The score reflects TF-IDF relevance ranking.
  </Accordion>

  <Accordion title="Does full-text search support stemming?">
    Yes. Full-text indexes leverage RediSearch which supports stemming, stopwords, and phonetic matching for more flexible text search.
  </Accordion>

  <Accordion title="Can I create full-text indexes on relationships?">
    Yes. Use `db.idx.fulltext.queryRelationships('RelType', 'search term')` to search relationships. Create the index on a relationship type similarly to node indexes.
  </Accordion>

  <Accordion title="How do I delete a full-text index?">
    Use `CALL db.idx.fulltext.drop('Label')` to remove the full-text index associated with a given label.
  </Accordion>
</AccordionGroup>
