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

# NodeSet Grouping

> Tag each memory with node sets so one graph keeps several overlapping topics apart

A minimal guide to grouping memories with node sets. Use it when one dataset holds several topics and you want each memory labeled — including memories that belong to more than one group — so you can see and later query those slices separately.

## Before You Start

* Complete [Quickstart](/getting-started/quickstart) to understand basic operations
* Ensure you have [LLM Providers](/setup-configuration/llm-providers) and [Embedding Providers](/setup-configuration/embedding-providers) configured
* Read [NodeSets](/core-concepts/further-concepts/node-sets) for how tags become graph nodes
* No data is required up front — the script ingests its own passages, but it starts with `cognee.forget(everything=True)`, which wipes all existing Cognee data; run it against a setup you can afford to reset

## Code in Action

```python theme={null}
import asyncio
import os

import cognee
from cognee import visualize_graph
from cognee.shared.logging_utils import ERROR, setup_logging

text_a = """
    AI is revolutionizing financial services through intelligent fraud detection
    and automated customer service platforms.
    """

text_b = """
    Advances in AI are enabling smarter systems that learn and adapt over time.
    """

text_c = """
    MedTech startups have seen significant growth in recent years, driven by innovation
    in digital health and medical devices.
    """

node_set_a = ["AI", "FinTech"]
node_set_b = ["AI"]
node_set_c = ["MedTech"]


async def main():
    await cognee.forget(everything=True)

    await cognee.remember(text_a, node_set=node_set_a, self_improvement=False)
    await cognee.remember(text_b, node_set=node_set_b, self_improvement=False)
    await cognee.remember(text_c, node_set=node_set_c, self_improvement=False)

    visualization_path = os.path.join(
        os.path.dirname(__file__), ".artifacts", "nodeset_grouping.html"
    )
    await visualize_graph(visualization_path)


if __name__ == "__main__":
    logger = setup_logging(log_level=ERROR)
    asyncio.run(main())
```

## What Just Happened

### Step 1: Plan the Groups

```python theme={null}
node_set_a = ["AI", "FinTech"]
node_set_b = ["AI"]
node_set_c = ["MedTech"]
```

Each list is the set of labels one passage carries. `text_a` sits in two groups at once (`AI` and `FinTech`), `text_b` only in `AI`, and `text_c` only in `MedTech` — node sets overlap freely, so a memory does not have to pick a single home.

### Step 2: Tag Each Memory on Ingest

```python theme={null}
await cognee.remember(text_a, node_set=node_set_a, self_improvement=False)
await cognee.remember(text_b, node_set=node_set_b, self_improvement=False)
await cognee.remember(text_c, node_set=node_set_c, self_improvement=False)
```

`node_set` is applied while the graph is built, so the labels are materialized as `NodeSet` nodes and attached to the derived chunks and entities with `belongs_to_set` edges. `self_improvement=False` keeps the run to plain ingestion instead of also running `improve()`.

### Step 3: Render the Grouped Graph

```python theme={null}
visualization_path = os.path.join(
    os.path.dirname(__file__), ".artifacts", "nodeset_grouping.html"
)
await visualize_graph(visualization_path)
```

The render writes a self-contained HTML file next to the script under `.artifacts/`. Open it and recolor the nodes by **Node set**: each document contributes one key, so `text_a`'s nodes show as `AI, FinTech` while `text_b` shows as `AI` and `text_c` as `MedTech`. To see the overlap itself, follow the `belongs_to_set` edges out of the `AI` NodeSet node — they reach the entities extracted from both `text_a` and `text_b`.

## Advanced Usage

The labels the script wrote at ingest time are read back at query time. Each option below builds on the same `AI`, `FinTech`, and `MedTech` groups the script just created.

<AccordionGroup>
  <Accordion title="Scope Recall to One Group">
    The same names you passed to `remember()` scope a later `recall()` through `node_name`. This is the payoff of tagging: one dataset holds all three topics, but a query can be grounded in a single slice of it.

    ```python theme={null}
    from cognee import SearchType

    # Recall only within the FinTech subset
    results = await cognee.recall(
        "What is happening in financial services?",
        query_type=SearchType.GRAPH_COMPLETION,
        node_name=["FinTech"],
    )
    ```

    In practice this lets you keep one shared dataset while still asking targeted questions — "only the finance material", "just the MedTech passages" — without splitting everything into separate datasets.
  </Accordion>

  <Accordion title="Combine Several Node Sets">
    Pass several names to widen the slice. `node_name_filter_operator` controls how they combine: the default `OR` returns results connected to any of the listed names, while `AND` requires results to belong to all of them at once.

    ```python theme={null}
    from cognee import SearchType

    # OR (default) — anything tagged AI or MedTech
    results = await cognee.recall(
        "What are the key topics?",
        query_type=SearchType.GRAPH_COMPLETION,
        node_name=["AI", "MedTech"],
        node_name_filter_operator="OR",
    )

    # AND — only what sits in both AI and FinTech, i.e. text_a
    results = await cognee.recall(
        "How is AI used in finance?",
        query_type=SearchType.GRAPH_COMPLETION,
        node_name=["AI", "FinTech"],
        node_name_filter_operator="AND",
    )
    ```

    <Note>
      Node-set filtering works with graph-completion search types (`GRAPH_COMPLETION`, `GRAPH_COMPLETION_COT`, `GRAPH_COMPLETION_CONTEXT_EXTENSION`, `GRAPH_SUMMARY_COMPLETION`, `TEMPORAL`, `RAG_COMPLETION`, `TRIPLET_COMPLETION`, `CHUNKS`). It has no effect on `SUMMARIES`, `CYPHER`, or `NATURAL_LANGUAGE`.
    </Note>
  </Accordion>

  <Accordion title="Navigate Data by Project or Domain">
    Because node sets become first-class graph nodes, they can act as anchors for exploration as well as filtering. A project-level label like `project_alpha` or a domain-level label like `compliance` gives you a stable entry point into the related documents, chunks, and entities.

    This makes node sets a lightweight way to organize one knowledge graph around the mental model your team already uses: project, customer, topic, workflow, or domain.

    ```python theme={null}
    # Tag documents by project and domain during ingestion
    await cognee.remember(
        "Project Alpha must satisfy EU compliance requirements.",
        node_set=["project_alpha", "compliance"],
    )

    await cognee.remember(
        "Project Alpha rollout depends on infrastructure readiness.",
        node_set=["project_alpha", "operations"],
    )
    ```

    After the `remember()` workflow finishes, `project_alpha`, `compliance`, and `operations` become graph anchors you can use to explore related information by project or by domain.
  </Accordion>
</AccordionGroup>

<Columns cols={3}>
  <Card title="NodeSets" icon="tags" href="/core-concepts/further-concepts/node-sets">
    How tags become first-class graph nodes you can filter on.
  </Card>

  <Card title="Graph Visualization" icon="network" href="/guides/graph-visualization">
    Render your knowledge graph to an interactive HTML file.
  </Card>

  <Card title="remember()" icon="brain" href="/python-api/remember">
    Every parameter `remember()` accepts, including `node_set`.
  </Card>
</Columns>
