---
title: "Map operations"
description: "Guide to the C# client's MapOperation builders for server-side map CDT operations with AerospikeClient.Operate()."
---

# Map operations

> For the complete documentation index see: [llms.txt](https://aerospike.com/docs/llms.txt)
> 
> All documentation pages available in markdown.

Aerospike’s map [collection data type](https://aerospike.com/docs/develop/data-types/collections) (CDT) operations let the server change, read, and remove individual map entries in a single round trip, while the client reads only the operation results. A _map bin_ stores key-value pairs. Keys are strings, integers, or byte arrays, and values can be any supported data type.

`AerospikeClient.Put` always replaces the full bin value. To change entries of a map bin that already exists, use the `MapOperation` builders with [`AerospikeClient.Operate()`](https://aerospike.com/docs/develop/client/csharp/usage/atomic/multi). Each builder returns an `Operation`, and the server runs the operations in the order you pass them.

## Setup

```csharp
using Aerospike.Client;

using System.Collections;

using System.Collections.Generic;

using System.Linq;

// Define host configuration

Host config = new Host("127.0.0.1", 3000);

// Establishes a connection to the server

AerospikeClient client = new AerospikeClient(null, config);
```

> 📖 **API reference**: [`MapOperation`](https://aerospike.com/apidocs/csharp/api/Aerospike.Client.MapOperation.html) | [`MapPolicy`](https://aerospike.com/apidocs/csharp/api/Aerospike.Client.MapPolicy.html) | [`MapReturnType`](https://aerospike.com/apidocs/csharp/api/Aerospike.Client.MapReturnType.html)

## Write a map bin

To write a map as the whole value of a bin, pass a `Dictionary<object, object>` to a `Bin`:

```csharp
Key key = new Key("sandbox", "stats", "page:1");

Dictionary<object, object> daily = new Dictionary<object, object> { { "2026-10-01", 5 } };

client.Put(null, key, new Bin("daily", daily));
```

## Increment counters in a map

`MapOperation.Increment(policy, binName, key, amount)` adds `amount` to the number stored under `key`. If the key doesn’t exist yet, the server creates it and sets it to `amount`. No read is required first. Pass `MapPolicy.Default` for the default map policy.

Pass several increments in one `Operate()` call to change several keys in a single round trip. When one call runs several operations on the same bin, the `Record` holds one bin whose value is a list of results, one for each operation, in order. Each result is the key’s new value:

```csharp
Record record = client.Operate(null, key,

    MapOperation.Increment(MapPolicy.Default, "daily", Value.Get("2026-10-01"), Value.Get(1)),

    MapOperation.Increment(MapPolicy.Default, "daily", Value.Get("2026-10-02"), Value.Get(1))

);

// The results are the new values, in the order of the operations

foreach (object newValue in record.GetList("daily"))

{

    Console.WriteLine(newValue);

}
```

## Read a map back

`record.GetMap(binName)` returns a map bin as an `IDictionary`. A default map is unordered, so the entries can come back in any order. To print them in key order, sort them in your program, or create the bin as a `KEY_ORDERED` map with a `MapPolicy`:

```csharp
Record record = client.Get(null, key);

IDictionary counters = record.GetMap("daily");

foreach (string date in counters.Keys.Cast<string>().OrderBy(k => k))

{

    Console.WriteLine("{0}: {1}", date, counters[date]);

}
```

## Select entries by rank

The _rank_ of an entry is its position when the server sorts the entries by value. Rank `0` is the entry with the lowest value. A negative rank counts from the highest value, so `-1` is the highest.

`MapOperation.GetByRankRange(binName, rank, count, returnType)` selects `count` entries that start at `rank`. To read the three highest-scoring players of a leaderboard, start at rank `-3`:

```csharp
Key boardKey = new Key("sandbox", "games", "board:1");

Dictionary<object, object> scores = new Dictionary<object, object>

{

    { "ann", 120 }, { "bob", 340 }, { "cat", 90 }, { "dan", 500 }, { "eve", 275 }

};

client.Put(null, boardKey, new Bin("scores", scores));

Record record = client.Operate(null, boardKey,

    MapOperation.GetByRankRange("scores", -3, 3, MapReturnType.KEY_VALUE)

);

// The entries come back from the lowest of the three scores to the highest

IList entries = (IList)record.GetValue("scores");

for (int i = entries.Count - 1; i >= 0; i--)

{

    KeyValuePair<object, object> entry = (KeyValuePair<object, object>)entries[i];

    Console.WriteLine("{0}: {1}", entry.Key, entry.Value);

}
```

`MapReturnType.KEY_VALUE` returns the selected entries as a list of `KeyValuePair<object, object>` in rank order. The server selects the entries, so the program doesn’t fetch and sort the whole map.

## Remove a key and return its value

`MapOperation.RemoveByKey(binName, key, returnType)` removes one entry from the map. The return type selects what the server sends back about the removed entry. To remove a key and get its value in the same call, use `MapReturnType.VALUE`:

```csharp
Key profileKey = new Key("sandbox", "settings", "user:1");

Dictionary<object, object> prefs = new Dictionary<object, object>

{

    { "lang", "en" }, { "theme", "dark" }, { "beta", "on" }

};

client.Put(null, profileKey, new Bin("prefs", prefs));

Record record = client.Operate(null, profileKey,

    MapOperation.RemoveByKey("prefs", Value.Get("beta"), MapReturnType.VALUE)

);

Console.WriteLine("removed: {0}", record.GetValue("prefs"));
```

The other entries stay in the map. The client sends a single map operation instead of reading and writing the whole bin.

## Choose what an operation returns

Map read and remove operations take a `MapReturnType` that selects what the server returns for the entries the operation selected:

| `MapReturnType` | What the server returns |
| --- | --- |
| `NONE` | Nothing. |
| `COUNT` | The number of entries selected. |
| `KEY` | The key of a single entry, or a list of keys for a range. |
| `VALUE` | The value of a single entry, or a list of values for a range. |
| `KEY_VALUE` | The entries as a list of `KeyValuePair<object, object>`. |
| `INDEX` | The key-order position of the entry, where `0` is the first key. |
| `REVERSE_INDEX` | The position in reverse key order, where `0` is the last key. |
| `RANK` | The rank of the entry, where `0` is the lowest value. |
| `REVERSE_RANK` | The rank in reverse value order, where `0` is the highest value. |
| `EXISTS` | `true` if the operation selected at least one entry. |

For range and list operations such as `RemoveByKeyRange`, add `MapReturnType.INVERTED` with the `|` operator. For example, `MapReturnType.KEY | MapReturnType.INVERTED` applies the operation to entries outside the selection.

For nested-map navigation with a nested CDT context (`CTX`), see the [`MapOperation`](https://aerospike.com/apidocs/csharp/api/Aerospike.Client.MapOperation.html) API reference and [Context for operations on nested elements](https://aerospike.com/docs/develop/data-types/collections/context).

## Next steps

-   [List operations](https://aerospike.com/docs/develop/client/csharp/usage/cdt/lists)
-   [Bin operations](https://aerospike.com/docs/develop/client/csharp/usage/atomic/multi)
-   [Map data type](https://aerospike.com/docs/develop/data-types/collections/map)