I added comments to detail the question in hand and my attempts to solve it.
pragma solidity ^0.4.19;
contract Users {
// a user with some metadata
struct User {
bytes32 name;
bytes32 email;
}
// users are aggregated (notice the array) by a unique key
mapping(uint => User[]) internal users;
// and of course we keep track of these unique keys
// because we can't loop through a mapping
uint[] internal keys;
function signUp(bytes32 name, bytes32 email) public {
// our unique key, users are aggregated by day
uint key = now / 1 days;
// if this is the first user within a key, we keep track of that key
if (users[key].length == 0) keys.push(key);
// we push the new user to the key's array of users
users[key].push(User(name, email));
}
// so far so good, now we move on to retrieving the data
// this answers the question of: in what keys there are users?
// one call, we get all the keys, efficient
function getKeys() public view returns (uint[]) {
return keys;
}
// now we need to answer the question of: who are the users of the key x?
// throws, Error: Unsupported or invalid type: tuple
function getUsers(uint key) public view returns(User[]) {
return users[key];
}
// the following approach works
// but requires users[key].length calls to the network, not efficient
// first, we need the number of indices within a key
function getUsersCount(uint key) public view returns (uint) {
return users[key].length;
}
// then, we need to loop getUsersCount(key) times
// to retrieve the metadata for each user
// throws, Error: Unsupported or invalid type: tuple
function getUser(uint key, uint index) public view returns(User) {
return users[key][index];
}
// same error from before, let's try this
function getUserModified(uint key, uint index) public view returns(bytes32, bytes32) {
User memory user = users[key][index];
return (user.name, user.email);
}
// works ..
// aha! so returns(User) is not supported, we have to destruct
// or is this limitation of Remix only?
// the question now is ..
// how can we return an array of (user.name, user.email)?
// that is, modifying faulty getUsers(), to avoid multiple getUserModified() calls
}
bytes32[] names; bytes32[] emails[];and not use structs at all, but that doesn't look good to me, is this how all apps do it nowadays? what if we have 10k users, that network call would be very costly with this new design – user5470921 Feb 13 '18 at 20:36uint[] foo;is already there, but returning an array within a struct or an array within a mapping (I am guessing also a nested array within an array) seems to be cumbersome. – user5470921 Feb 13 '18 at 23:42ethersfor the past hour as it has full support for it already, wonderful library I must say, I already like it better thanweb3. So it's not a solidity thing after all, no luck so far I'll update here if I end up with a positive outcome. – user5470921 Feb 14 '18 at 02:17pragma experimental ABIEncoderV2;would still be needed for now. – user5470921 Feb 16 '18 at 03:15