[Ethereum] Storing multiple values in one key mapping (Solidity)

mappingremixsoliditystorage

Can I store multiple values in one key mapping in solidity? like I can retrieve all of the values if I use that one mapping key? Is this possible?

Best Answer

It's not clear if you want to retrieve all the values in a mapping or use the mapping to store structures that contain interesting, multipart things.

No to the first interpretation.

Yes to the second.

Lay out an instance (for one key) in a struct. Map the structs to the keys.

struct MyStruct {
  uint part1;
  bool part2;
  ...
}

mapping(uint => MyStruct) public myStructs;

It's also possible to store arrays and more mappings in a struct. The getters and setters get more interesting than the "free" getter you get with this public mapping of scaler types.

UPDATE

Upon reflection, I realized there is a third interpretation.

  • Pass the entire mapping around, without interpretation.

No, to externally.

Yes, to internally.

You can pass a mapping internally by sending only the storage pointer. A storage pointer reduces the object to 1 32-byte word from which all slots in the mapping can be deduced. As such, it is meaningless externally and external opinions about can't be trusted. Therefore, functions that do that must be marked internal or private. If that sounds cryptic, have a look at https://blog.b9lab.com/storage-pointers-in-solidity-7dcfaa536089.

You can pass structs this way, and mappings can reside in structs, so ...

Have a look at:

pragma solidity 0.5.12;

    contract ArrayMapping {

    struct MyStruct {
        uint part1;
        bool part2;
    }

    struct MapStruct {
        mapping(uint => MyStruct) myStructs;   
    }

    MapStruct map;

    function get(uint index) public view returns(uint, bool) {
        return fetch(map, index);
    }

    function fetch(MapStruct storage m, uint index) internal view returns(uint, bool) {
        return (m.myStructs[index].part1, m.myStructs[index].part2);
    }
}

A "storage pointer" to the struct that contains a mapping is passed into fetch. This doesn't help fetch iterate, count or otherwise understand the contents of the mapping but it gives it the raw material to get started.

You can pass structs around to/from libraries and that can help compartmentalize logic that is focused on complex storage structures. See https://github.com/rob-Hitchens/UnorderedKeySet and https://medium.com/hackernoon/binary-search-trees-and-order-statistics-for-ethereum-db47e2dd2c36 for examples.

Hope it helps.

Related Topic