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

# Collections

> Efficiently store, access, and manage data in smart contracts.

export const Github = ({url, start, end, fname, withSourceLink = true}) => {
  const [code, setCode] = useState(null);
  function toRaw(ref) {
    const fullUrl = ref.slice(ref.indexOf('https'));
    const [url] = fullUrl.split('#');
    const [org, repo, , branch, ...pathSeg] = new URL(url).pathname.split('/').slice(1);
    return `https://raw.githubusercontent.com/${org}/${repo}/${branch}/${pathSeg.join('/')}`;
  }
  async function fetchCode(url, fromLine, toLine) {
    let res;
    if (typeof window !== 'undefined') {
      const validUntil = localStorage.getItem(`${url}-until`);
      if (validUntil && Number(validUntil) > Date.now()) {
        res = localStorage.getItem(url);
      }
    }
    if (!res) {
      try {
        res = await (await fetch(url)).text();
        if (typeof window !== 'undefined') {
          localStorage.setItem(url, res);
          localStorage.setItem(`${url}-until`, String(Date.now() + 60000));
        }
      } catch {
        return 'Error fetching code, please try reloading';
      }
    }
    let body = res.split('\n');
    const from = fromLine ? Number(fromLine) - 1 : 0;
    const to = toLine ? Number(toLine) : body.length;
    body = body.slice(from, to);
    const precedingSpace = body.reduce((prev, line) => {
      if (line.length === 0) return prev;
      const spaces = line.match(/^\s+/);
      if (spaces) return Math.min(prev, spaces[0].length);
      return 0;
    }, Infinity);
    return body.map(line => line.slice(precedingSpace === Infinity ? 0 : precedingSpace)).join('\n');
  }
  function buildSourceUrl(url, start, end) {
    const base = url.split('#')[0];
    if (start && end) return `${base}#L${start}-L${end}`;
    if (start) return `${base}#L${start}`;
    return base;
  }
  useEffect(() => {
    const rawUrl = toRaw(url);
    fetchCode(rawUrl, start, end).then(res => setCode(res));
  }, [url, start, end]);
  const sourceUrl = buildSourceUrl(url, start, end);
  const startLine = start ? Number(start) : 1;
  const fileName = fname ?? sourceUrl.split('/').pop();
  return <div className="rounded-[0.625rem] border border-[#d0d7de] dark:border-[#30363d] overflow-hidden my-5 text-[0.8125rem] font-mono shadow-sm dark:shadow-[0_4px_24px_rgba(0,0,0,0.18)]">

      {}
      <div className="flex items-center justify-between py-2 px-[0.875rem] bg-[#f6f8fa] dark:bg-[#161b22] border-b border-[#d0d7de] dark:border-[#30363d]">
        <div className="flex items-center gap-2 text-[#656d76] dark:text-[#8b949e]">
          <svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor">
            <path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0 0 24 12c0-6.63-5.37-12-12-12z" />
          </svg>
          <span className="text-xs font-medium text-[#1f2328] dark:text-[#e6edf3]">
            {fileName}
          </span>
        </div>
        {start && end && <span className="text-[0.6875rem] text-[#656d76] dark:text-[#8b949e] bg-[#eaeef2] dark:bg-[#21262d] border border-[#d0d7de] dark:border-[#30363d] rounded-full py-0.5 px-2">
            Lines {start}–{end}
          </span>}
      </div>

      {}
      <div className="overflow-auto max-h-[480px] bg-white dark:bg-[#0d1117] [&_tr]:border-b-0 [&_td]:border-b-0">
        {code === null ? <div className="py-5 px-4 text-xs text-[#656d76] dark:text-[#6e7681]">
            Loading...
          </div> : <table className="w-full border-collapse leading-[1.6]">
            <tbody>
              {code.split('\n').map((line, i) => <tr key={i} className="align-top border-0">
                  <td style={{
    minWidth: '60px'
  }} className="select-none pl-2 pr-3 text-right text-[0.7rem] text-[#8c959f] dark:text-[#3d444d] w-[1%] whitespace-nowrap border-r border-0 border-r-[#d0d7de] dark:border-r-[#21262d]">
                    {startLine + i}
                  </td>
                  <td className="pl-4 pr-6 text-[0.8125rem] text-[#1f2328] dark:text-[#e6edf3] whitespace-pre">
                    {line || ' '}
                  </td>
                </tr>)}
            </tbody>
          </table>}
      </div>

      {}
      {withSourceLink && <div className="flex justify-end py-1.5 px-[0.875rem] bg-[#f6f8fa] dark:bg-[#161b22] border-t border-[#d0d7de] dark:border-[#21262d]">
          <a href={sourceUrl} target="_blank" rel="noreferrer noopener" className="text-[0.6875rem] font-medium text-[#656d76] dark:text-[#8b949e] no-underline flex items-center gap-[0.3rem] hover:text-[#1f2328] dark:hover:text-[#e6edf3] transition-colors">
            View on GitHub
            <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
              <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
              <polyline points="15 3 21 3 21 9" />
              <line x1="10" y1="14" x2="21" y2="3" />
            </svg>
          </a>
        </div>}
    </div>;
};

When deciding on data structures it is important to understand their tradeoffs. Choosing the wrong structure can create a bottleneck as the application scales, and migrating the state to the new data structures will come at a cost.

You can choose between two types of collections:

1. Native collections (e.g. `Array`, `Map`, `Set`), provided by the language
2. SDK collections (e.g. `IterableMap`, `Vector`), provided by the NEAR SDK

<Tip>
  **Native vs SDK Collections**

  Use native collections for small amounts of data that need to be accessed altogether, and SDK collections for large amounts of data that do not need to be accessed altogether.

  If your collection has up to 100 entries, it's acceptable to use the native collection. For larger ones, prefer to use SDK collection. For comparison please refer to [this benchmark](https://www.github.com/volodymyr-matselyukh/near-benchmarking).
</Tip>

***

## Storage Management

Each time the contract is executed, the first thing it will do is to read the values and [deserialize](./serialization) them into memory, and after the function finishes, it will [serialize](./serialization) and write the values back to the database.

For native collections, the contract will fully load the collection into memory before any method executes. This happens even if the method you invoke does not use the collection. Know that this will have impact on GAS you spend for methods in your contract.

<Accordion title="Storage Cost">
  Your contract needs to lock a portion of their balance proportional to the amount of data they stored in the blockchain. This means that:

  * If more data is added the **storage increases ↑**, and your contract's **balance decreases ↓**.
  * If data is deleted the **storage decreases ↓**, and your contract's **balance increases ↑**.

  Currently, it costs approximately **1 Ⓝ** to store **100kb** of data.
</Accordion>

<Accordion title="Storage Constraints on NEAR">
  For storing data on-chain it’s important to keep in mind the following:

  * There is a 4mb limit on how much you can upload at once

  Let’s say for example, someone wants to put an NFT purely on-chain (rather than IPFS or some other decentralized storage solution) you’ll have almost an unlimited amount of storage but will have to pay 1 `$NEAR` per 100kb of storage used.

  Users will be limited to 4MB per contract call upload due to MAX\_GAS constraints. The maximum amount of gas one can attach to a given functionCall is 300TGas.
</Accordion>

<Warning>
  Your contract will panic if you try to store data but don't have NEAR to cover its storage cost
</Warning>

<Danger>
  Be mindful of potential [small deposit attacks](../security/storage)
</Danger>

***

## Native Collections

Native collections are those provided by the language, such as `Array`, `Map`, `Set` in Javascript, or `Vec`, `HashMap`, `HashSet` in Rust.

All entries in a native collection are **serialized into a single value** and **stored together** into the state. This means that every time a function execute, the SDK will read and **deserialize all entries** in the native collection.

<Accordion title="Serialization & Storage Example">
  The array `[1,2,3,4]` will be serialized into the JSON string `"[1,2,3,4]"` in Javascript, and the Borsh byte-stream `[0,0,0,4,1,2,3,4]` in Rust before being stored
</Accordion>

<Tip>
  **When to use them**

  Native collections are useful if you are planning to store smalls amounts of data that need to be accessed all together
</Tip>

<Danger>
  **Keep Native Collections Small**

  As the native collection grows, deserializing it from memory will cost more and more gas. If the collections grows too large, your contract might expend all the gas trying to read its state, making it fail on each function call
</Danger>

***

## SDK Collections

The NEAR SDKs expose collections that are optimized for random access of large amounts of data. SDK collections are instantiated using a "prefix", which is used as an index to split the data into chunks. This way, SDK collections can defer reading and writing to the store until needed.

<Accordion title="Serialization & Storage Example">
  The sdk array `[1,2,3,4]` with prefix `"p"` will be stored as the string `"p"` in the contract's attribute, and create four entries in the contract's storage: `p-0:1`, `p-1:2`...
</Accordion>

<Accordion title="SDK Collections' Features">
  | Type           | Iterable | Clear All Values | Preserves Insertion Order | Range Selection |
  | -------------- | :------: | :--------------: | :-----------------------: | :-------------: |
  | `Vector`       |     ✅    |         ✅        |             ✅             |        ✅        |
  | `LookupSet`    |          |                  |                           |                 |
  | `UnorderedSet` |     ✅    |         ✅        |                           |        ✅        |
  | `IterableSet`  |     ✅    |         ✅        |                           |        ✅        |
  | `LookupMap`    |          |                  |                           |                 |
  | `UnorderedMap` |     ✅    |         ✅        |                           |        ✅        |
  | `IterableMap`  |     ✅    |         ✅        |                           |        ✅        |
  | `TreeMap`      |     ✅    |         ✅        |             ✅             |        ✅        |
</Accordion>

<Accordion title="SDK Collections' Time Complexities">
  | Type           | Access |  Insert  |  Delete  |  Search  | Traverse | Clear |
  | -------------- | :----: | :------: | :------: | :------: | :------: | :---: |
  | `Vector`       |  O(1)  |  O(1)\*  | O(1)\*\* |   O(n)   |   O(n)   |  O(n) |
  | `LookupSet`    |  O(1)  |   O(1)   |   O(1)   |   O(1)   |    N/A   |  N/A  |
  | `UnorderedSet` |  O(1)  |   O(1)   |   O(1)   |   O(1)   |   O(n)   |  O(n) |
  | `IterableSet`  |  O(1)  |   O(1)   |   O(1)   |   O(1)   |   O(n)   |  O(n) |
  | `LookupMap`    |  O(1)  |   O(1)   |   O(1)   |   O(1)   |    N/A   |  N/A  |
  | `IterableMap`  |  O(1)  |   O(1)   |   O(1)   |   O(1)   |   O(n)   |  O(n) |
  | `TreeMap`      |  O(1)  | O(log n) | O(log n) | O(log n) |   O(n)   |  O(n) |

  *\* - to insert at the end of the vector using `push_back` (or `push_front` for deque)*
  *\*\* - to delete from the end of the vector using `pop` (or `pop_front` for deque), or delete using `swap_remove` which swaps the element with the last element of the vector and then removes it.*
</Accordion>

These collections are built to have an interface similar to native collections.

<Tip>
  **when to use them**

  SDK collections are useful when you are planning to store large amounts of data that do not need to be accessed all together
</Tip>

### Instantiation

All structures need to be initialized using a **unique `prefix`**, which will be used to index the collection's values in the account's state

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="lib.rs" language="rust" url="https://github.com/near-examples/storage-examples/blob/main/collections-rs/store/src/lib.rs" start="24" end="47" />

    <Tip>
      Notice how we use `enums` to ensure all collections have a different prefix. Another advantage of using `enums` is that they are serialized into a single `byte` prefix.
    </Tip>
  </Tab>

  <Tab title="🌐 JavaScript">
    <Github fname="contract.ts" language="js" url="https://github.com/near-examples/storage-examples/blob/main/collections-js/src/contract.ts" start="6" end="25" />

    <Tip>
      Do not forget to use the `schema` to define how your contract's state is structured
    </Tip>
  </Tab>

  <Tab title="🐍 Python">
    ```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
    from near_sdk_py import view, call, init
    from near_sdk_py.collections import Vector, LookupMap, UnorderedMap, LookupSet, UnorderedSet

    class MyContract:
        @init
        def new(self): # Create a Vector with prefix "v"
            self.my_vector = Vector("v")

            # Create a LookupMap with prefix "m"
            self.my_lookup_map = LookupMap("m")

            # Create an UnorderedMap with prefix "um"
            self.my_unordered_map = UnorderedMap("um")

            # Create a LookupSet with prefix "s"
            self.my_lookup_set = LookupSet("s")

            # Create an UnorderedSet with prefix "us"
            self.my_unordered_set = UnorderedSet("us")

            # For nested collections, use different prefixes
            self.nested_maps = UnorderedMap("nested")

            return True

        @call
        def create_nested_map(self, key: str):
            # Create a new map that will be stored inside another map
            inner_map = UnorderedMap(f"inner_{key}")
            self.nested_maps[key] = inner_map
            return {"success": True}

    ```
  </Tab>

  <Tab title="🐹 GO">
    <Github fname="main.go" language="go" url="https://github.com/Emir-Asanov/near-go-examples/blob/example-release-1/collections/main.go" start="7" end="29" />
  </Tab>
</Tabs>

<Danger>
  Be careful of not using the same prefix in two collections, otherwise, their storage space will collide, and you might overwrite information from one collection when writing in the other
</Danger>

<hr className="subsection" />

### Vector

Implements a [vector/array](https://en.wikipedia.org/wiki/Array_data_structure) which persists in the contract's storage. Please refer to the Rust and JS SDK's for a full reference on their interfaces.

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="vector.rs" language="rust" url="https://github.com/near-examples/storage-examples/blob/main/collections-rs/store/src/vector.rs" start="4" end="29" />
  </Tab>

  <Tab title="🌐 JavaScript">
    <Github fname="contract.ts" language="js" url="https://github.com/near-examples/storage-examples/blob/main/collections-js/src/contract.ts" start="48" end="73" />
  </Tab>

  <Tab title="🐍 Python">
    ```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
    from near_sdk_py import view, call, init
    from near_sdk_py.collections import Vector

    class VectorExample:
        @init
        def new(self):
            # Create a Vector with prefix "v"
            self.my_vector = Vector("v")

        @call
        def add_number(self, number):
            # Append a value to the vector
            self.my_vector.append(number)
            return len(self.my_vector)

        @view
        def get_number(self, index):
            # Get a value at specific index
            try:
                return self.my_vector[index]
            except Exception:
                return None

        @view
        def get_all_numbers(self):
            # Convert entire vector to a list
            return [num for num in self.my_vector]
    ```
  </Tab>

  <Tab title="🐹 GO">
    <Github fname="main.go" language="go" url="https://github.com/Emir-Asanov/near-go-examples/blob/example-release-1/collections/main.go" start="33" end="58" />
  </Tab>
</Tabs>

<hr className="subsection" />

### LookupMap

Implements a [map/dictionary](https://en.wikipedia.org/wiki/Associative_array) which persists in the contract's storage. Please refer to the Rust and JS SDK's for a full reference on their interfaces.

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="lookup_map.rs" language="rust" url="https://github.com/near-examples/storage-examples/blob/main/collections-rs/store/src/lookup_map.rs" start="4" end="22" />
  </Tab>

  <Tab title="🌐 JavaScript">
    <Github fname="contract.ts" language="js" url="https://github.com/near-examples/storage-examples/blob/main/collections-js/src/contract.ts" start="111" end="131" />
  </Tab>

  <Tab title="🐍 Python">
    ```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
    from near_sdk_py import view, call, init
    from near_sdk_py.collections import LookupMap

    class LookupMapExample:
        @init
        def new(self):
            # Create a LookupMap with prefix "m"
            self.balances = LookupMap("m")

        @call
        def set_balance(self, account_id, amount):
            # Set a value for a key
            self.balances[account_id] = amount
            return True

        @view
        def get_balance(self, account_id):
            # Get a value for a key with a default
            return self.balances.get(account_id, 0)

        @call
        def remove_balance(self, account_id):
            # Remove a key
            if account_id in self.balances:
                del self.balances[account_id]
                return True
            return False
    ```
  </Tab>

  <Tab title="🐹 GO">
    <Github fname="main.go" language="go" url="https://github.com/Emir-Asanov/near-go-examples/blob/example-release-1/collections/main.go" start="62" end="85" />
  </Tab>
</Tabs>

<hr className="subsection" />

### UnorderedMap / IterableMap

Implements a [map/dictionary](https://en.wikipedia.org/wiki/Associative_array) which persists in the contract's storage. Please refer to the Rust and JS SDK's for a full reference on their interfaces.

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="iterable_map.rs" language="rust" url="https://github.com/near-examples/storage-examples/blob/main/collections-rs/store/src/iterable_map.rs" start="4" end="29" />
  </Tab>

  <Tab title="🌐 JavaScript">
    <Github fname="contract.ts" language="js" url="https://github.com/near-examples/storage-examples/blob/main/collections-js/src/contract.ts" start="132" end="152" />
  </Tab>

  <Tab title="🐍 Python">
    ```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
    from near_sdk_py import view, call, init
    from near_sdk_py.collections import UnorderedMap

    class UnorderedMapExample:
        @init
        def new(self):
            # Create an UnorderedMap with prefix "um"
            self.user_data = UnorderedMap("um")

        @call
        def set_user_data(self, account_id, data):
            # Set a value for a key
            self.user_data[account_id] = data
            return True

        @view
        def get_user_data(self, account_id):
            # Get a value for a key
            try:
                return self.user_data[account_id]
            except Exception:
                return None

        @view
        def list_all_users(self):
            # Iterate through keys and values
            return {
                "keys": self.user_data.keys(),
                "values": self.user_data.values(),
                "items": self.user_data.items()
            }
    ```
  </Tab>

  <Tab title="🐹 GO">
    <Github fname="main.go" language="go" url="https://github.com/Emir-Asanov/near-go-examples/blob/example-release-1/collections/main.go" start="89" end="118" />
  </Tab>
</Tabs>

<hr className="subsection" />

### LookupSet

Implements a [set](https://en.wikipedia.org/wiki/Set_\(abstract_data_type\)) which persists in the contract's storage. Please refer to the Rust and JS SDK's for a full reference on their interfaces.

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="lookup_set.rs" language="rust" url="https://github.com/near-examples/storage-examples/blob/main/collections-rs/store/src/lookup_set.rs" start="4" end="18" />
  </Tab>

  <Tab title="🌐 JavaScript">
    <Github fname="contract.ts" language="js" url="https://github.com/near-examples/storage-examples/blob/main/collections-js/src/contract.ts" start="74" end="89" />
  </Tab>

  <Tab title="🐍 Python">
    ```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
    from near_sdk_py import view, call, init
    from near_sdk_py.collections import LookupSet

    class LookupSetExample:
        @init
        def new(self):
            # Create a LookupSet with prefix "s"
            self.whitelist = LookupSet("s")

        @call
        def add_to_whitelist(self, account_id):
            # Add a value to the set
            self.whitelist.add(account_id)
            return True

        @view
        def is_whitelisted(self, account_id):
            # Check if a value exists in the set
            return account_id in self.whitelist

        @call
        def remove_from_whitelist(self, account_id):
            # Remove a value from the set
            try:
                self.whitelist.remove(account_id)
                return True
            except Exception:
                return False
    ```
  </Tab>

  <Tab title="🐹 GO">
    <Github fname="main.go" language="go" url="https://github.com/Emir-Asanov/near-go-examples/blob/example-release-1/collections/main.go" start="122" end="136" />
  </Tab>
</Tabs>

<hr className="subsection" />

### UnorderedSet / IterableSet

Implements a [map/dictionary](https://en.wikipedia.org/wiki/Associative_array) which persists in the contract's storage. Please refer to the Rust and JS SDK's for a full reference on their interfaces.

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="iterable_set.rs" language="rust" url="https://github.com/near-examples/storage-examples/blob/main/collections-rs/store/src/iterable_set.rs" start="4" end="26" />
  </Tab>

  <Tab title="🌐 JavaScript">
    <Github fname="contract.ts" language="js" url="https://github.com/near-examples/storage-examples/blob/main/collections-js/src/contract.ts" start="90" end="110" />
  </Tab>

  <Tab title="🐍 Python">
    ```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
    from near_sdk_py import view, call, init
    from near_sdk_py.collections import UnorderedSet

    class UnorderedSetExample:
        @init
        def new(self):
            # Create an UnorderedSet with prefix "us"
            self.owners = UnorderedSet("us")

        @call
        def register_owner(self, account_id):
            # Add a value to the set
            self.owners.add(account_id)
            return True

        @view
        def is_owner(self, account_id):
            # Check if a value exists in the set
            return account_id in self.owners

        @view
        def list_all_owners(self):
            # Get all values as a list
            return self.owners.values()

        @call
        def remove_owner(self, account_id):
            # Try to remove a value if it exists
            self.owners.discard(account_id)
            return True
    ```
  </Tab>

  <Tab title="🐹 GO">
    <Github fname="main.go" language="go" url="https://github.com/Emir-Asanov/near-go-examples/blob/example-release-1/collections/main.go" start="140" end="160" />
  </Tab>
</Tabs>

<hr className="subsection" />

### Tree

An ordered equivalent of Map. The underlying implementation is based on an [AVL](https://en.wikipedia.org/wiki/AVL_tree). You should use this structure when you need to: have a consistent order, or access the min/max keys.

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="tree.rs" language="rust" url="https://github.com/near-examples/storage-examples/blob/main/collections-rs/legacy/src/tree.rs" start="6" end="24" />
  </Tab>

  <Tab title="🐍 Python">
    ```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
    from near_sdk_py import view, call, init
    from near_sdk_py.collections import TreeMap

    class TreeMapExample:
        @init
        def new(self):
            # Create a TreeMap with prefix "tm"
            self.scores = TreeMap("tm")

        @call
        def add_score(self, user_id, score):
            # Set score for a user
            self.scores[user_id] = score
            return True

        @view
        def get_top_scores(self, limit=10):
            # Get top scores using ordered keys
            top_users = []
            max_key = self.scores.max_key()
            current_key = max_key
            count = 0

            while current_key is not None and count < limit:
                top_users.append({
                    "user": current_key,
                    "score": self.scores[current_key]
                })
                current_key = self.scores.floor_key(current_key - 1)
                count += 1

            return top_users
    ```
  </Tab>

  <Tab title="🐹 GO">
    <Github fname="main.go" language="go" url="https://github.com/Emir-Asanov/near-go-examples/blob/example-release-1/collections/main.go" start="164" end="185" />
  </Tab>
</Tabs>

***

## Nesting Collections

When nesting SDK collections, be careful to **use different prefixes** for all collections, including the nested ones.

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="nested.ts" language="rust" url="https://github.com/near-examples/storage-examples/blob/main/collections-rs/store/src/nested.rs" start="4" end="30" />

    <Tip>
      Notice how we use `enums` that take a `String` argument to ensure all collections have a different prefix
    </Tip>
  </Tab>

  <Tab title="🌐 JavaScript">
    <Github fname="nested.ts" language="js" url="https://github.com/near-examples/storage-examples/blob/main/collections-js/src/contract.ts" start="153" end="196" />
  </Tab>

  <Tab title="🐍 Python">
    ```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
    from near_sdk_py import view, call, init
    from near_sdk_py.collections import UnorderedMap, Vector
    from near_sdk_py.collections import create_prefix_guard

    class NestedCollectionsExample:
        @init
        def new(self):
            # Main map of users to their assets
            self.user_assets = UnorderedMap("users")

        @call
        def add_asset(self, user_id, asset_id, metadata):
            # Get or create the user's assets vector with a unique prefix
            if user_id not in self.user_assets:
                # Create a prefix guard to ensure unique prefixes for this user
                prefix = f"assets:{user_id}"
                # Create a new vector for this user's assets
                self.user_assets[user_id] = Vector(prefix)

            # Add the asset to the user's assets vector
            user_assets = self.user_assets[user_id]
            user_assets.append({
                "asset_id": asset_id,
                "metadata": metadata
            })

            # Update the vector in the map
            self.user_assets[user_id] = user_assets
            return True

        @view
        def get_user_assets(self, user_id):
            if user_id not in self.user_assets:
                return []

            # Get all assets for the user
            user_assets = self.user_assets[user_id]
            return [asset for asset in user_assets]
    ```

    <Tip>
      In Python, we create unique prefixes for nested collections by including the parent's identifier in the prefix string. The SDK also provides a `create_prefix_guard` utility to help manage prefixes.
    </Tip>
  </Tab>

  <Tab title="🐹 GO">
    <Github fname="main.go" language="go" url="https://github.com/Emir-Asanov/near-go-examples/blob/example-release-1/collections/main.go" start="211" end="233" />

    <Tip>
      In Go, nested `Vector` collections must have their `Len` persisted separately (e.g., in a `LookupMap[string, uint64]`). When reconstructing a vector, pass the saved length via `&collections.Vector[string]{Prefix: prefix, Len: savedLen}`. Always use unique prefixes across all collections.
    </Tip>
  </Tab>
</Tabs>

***

## Error prone patterns

Because the values are not kept in memory and are lazily loaded from storage, it's important to make sure if a collection is replaced or removed, that the storage is cleared. In addition, it is important that if the collection is modified, the collection itself is updated in state because most collections will store some metadata.

Some error-prone patterns to avoid that cannot be restricted at the type level are:

<Tabs>
  <Tab title="🦀 Rust">
    ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
    use near_sdk::store::UnorderedMap;

    let mut m = UnorderedMap::<u8, String>::new(b"m");
    m.insert(1, "test".to_string());
    assert_eq!(m.len(), 1);
    assert_eq!(m.get(&1), Some(&"test".to_string()));

    // Bug 1: Should not replace any collections without clearing state, this will reset any
    // metadata, such as the number of elements, leading to bugs. If you replace the collection
    // with something with a different prefix, it will be functional, but you will lose any
    // previous data and the old values will not be removed from storage.
    m = UnorderedMap::new(b"m");
    assert!(m.is_empty());
    assert_eq!(m.get(&1), Some(&"test".to_string()));

    // Bug 2: Should not use the same prefix as another collection
    // or there will be unexpected side effects.
    let m2 = UnorderedMap::<u8, String>::new(b"m");
    assert!(m2.is_empty());
    assert_eq!(m2.get(&1), Some(&"test".to_string()));

    // Bug 3: forgetting to save the collection in storage. When the collection is attached to
    // the contract state (`self` in `#[near]`) this will be done automatically, but if
    // interacting with storage manually or working with nested collections, this is relevant.
    use near_sdk::store::Vector;

    // Simulate roughly what happens during a function call that initializes state.
    {
        let v = Vector::<u8>::new(b"v");
        near_sdk::env::state_write(&v);
    }

    // Simulate what happens during a function call that just modifies the collection
    // but does not store the collection itself.
    {
        let mut v: Vector<u8> = near_sdk::env::state_read().unwrap();
        v.push(1);
        // The bug is here that the collection itself if not written back
    }

    let v: Vector<u8> = near_sdk::env::state_read().unwrap();
    // This will report as if the collection is empty, even though the element exists
    assert!(v.get(0).is_none());
    assert!(
        near_sdk::env::storage_read(&[b"v".as_slice(), &0u32.to_le_bytes()].concat()).is_some()
    );

    // Bug 4 (only relevant for `near_sdk::store`): These collections will cache writes as well
    // as reads, and the writes are performed on [`Drop`](https://doc.rust-lang.org/std/ops/trait.Drop.html)
    // so if the collection is kept in static memory or something like `std::mem::forget` is used,
    // the changes will not be persisted.
    use near_sdk::store::IterableSet;

    let mut m: IterableSet<u8> = IterableSet::new(b"l");
    m.insert(1);
    assert!(m.contains(&1));

    // This would be the fix, manually flushing the intermediate changes to storage.
    // m.flush();
    std::mem::forget(m);

    m = IterableSet::new(b"l");
    assert!(!m.contains(&1));
    ```
  </Tab>

  <Tab title="🐹 GO">
    <Github fname="main.go" language="go" url="https://github.com/Emir-Asanov/near-go-examples/blob/example-release-1/collections/main.go" start="209" end="231" />
  </Tab>
</Tabs>

***

## Pagination

Persistent collections such as `IterableMap/UnorderedMap`, `IterableSet/UnorderedSet` and `Vector` may
contain more elements than the amount of gas available to read them all.
In order to expose them all through view calls, we can use pagination.

<Tabs>
  <Tab title="🦀 Rust">
    With Rust this can be done using iterators with [`Skip`](https://doc.rust-lang.org/std/iter/struct.Skip.html) and [`Take`](https://doc.rust-lang.org/std/iter/struct.Take.html). This will only load elements from storage within the range.

    ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
      #[near(contract_state)]
      #[derive(PanicOnDefault)]
      pub struct Contract {
          pub status_updates: IterableMap<AccountId, String>,
      }

      #[near]
      impl Contract {
          /// Retrieves multiple elements from the `IterableMap`.
          /// - `from_index` is the index to start from.
          /// - `limit` is the maximum number of elements to return.
          pub fn get_updates(&self, from_index: usize, limit: usize) -> Vec<(AccountId, String)> {
              self.status_updates
                  .iter()
                  .skip(from_index)
                  .take(limit)
                  .collect()
          }
      }
    ```
  </Tab>

  <Tab title="🌐 JavaScript">
    With JavaScript this can be done using iterators with [`toArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Iterator/toArray) and [`slice`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice).

    ```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
      /// Returns multiple elements from the `UnorderedMap`.
      /// - `from_index` is the index to start from.
      /// - `limit` is the maximum number of elements to return.
      @view({})
      get_updates({ from_index, limit }: { from_index: number, limit:number }) {
        return this.status_updates.toArray().slice(from_index, limit);
      }
    ```
  </Tab>

  <Tab title="🐍 Python">
    ```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
    # With Python this can be done using standard list slicing.

    @view
    def get_updates(self, from_index: int = 0, limit: int = 50) -> list:
        """Returns multiple elements from the collection with pagination."""
        all_items = self.status_updates.values()
        start = min(from_index, len(all_items))
        end = min(start + limit, len(all_items))
        return all_items[start:end]
    ```
  </Tab>

  <Tab title="🐹 GO">
    With Go this can be done using index-based iteration over a `Vector`, loading only the elements within the requested range.

    <Github fname="main.go" language="go" url="https://github.com/Emir-Asanov/near-go-examples/blob/example-release-1/collections/main.go" start="189" end="207" />
  </Tab>
</Tabs>
