I'm working on a project where I need to access users like you, while being able to add quickly. For this my current (barebones) data struct looks like
address lastAccess = 0x0;
struct User {
...
}
address mappingHead = 0x0;
mapping (address => address) public users;
mapping (address => User) public data;
Adding a user looks like
if(users[msg.sender] == 0x0 && msg.sender != mappingHead) {
users[mappingHead] = msg.sender;
mappingHead = msg.sender;
data[mappingHead] = new User(...);
}
Iteration to find a user looks like
address iterator = lastAccess;
uint256 iteration = 0;
while(iterator != 0x0) {
if(iteration++ > _maxIterations){
lastAccess = iterator;
iterator = 0x0; // Or break
} else {
if(data[iterator].x == X){
...
iterator = 0x0; // Or break
} else {
iterator = users[iterator];
}
}
}
Finding/modifying is O(N) for N _maxIterations in a single call and insertion/reading/accessing is O(1). This implementation does not support deletion, but you could add a "deleted" flag.
Another solution is to keep a bunch of property mappings.
struct User {
prop_1;
prop_2;
...
prop_n;
}
mapping (type => address) public prop_1;
mapping (type => address) public prop_2;
...
mapping (type => address) public prop_n;
mapping (address => User) public list;
Accessing is done by
// Switch on the property x
User u = list[prop_x[_prop_x]];
Adding is done by
prop_1[_prop_1] = msg.sender;
prop_2[_prop_2] = msg.sender;
...
prop_n[_prop_n] = msg.sender;
The problem with this implementation is that you will overwrite addresses for repeating properties. You could add an indexing on repeating properties, so as to know how many repeated properties are for each type, as above, but modified
// Redefine prop_1 as
// mapping(type => mapping(uint256 => address)) public prop_1;
if(prop_x[_prop_x][prop_x_count[_prop_x]] != 0x0)
prop_x_count[_prop_x]++;
prop_x[_prop_x][prop_x_count[_prop_x]] = msg.sender;
This is still subject to attacks on gas limits, but at least you could make partial searches as shown in the original version.
Note: this is untested code.