Was ist der effizienteste Weg, zwei verschiedene Schlüsseltypen einer Struktur zuzuordnen?

Im Code hier habe ich einen neuen Kunden namens „mcycleowner“ erstellt und ihn einer Eingabe-_Adresse zugeordnet. Ich möchte es jedoch auch der Eingabe _license zuordnen, damit Kundeninformationen entweder mit einer Eth-Adresse oder einem Kfz-Kennzeichen abgefragt werden können.

Dazu habe ich einen neuen Kunden „mcyclelicenses“ erstellt, und die Funktion addLicense nimmt die gleichen Eingaben wie newMcycleOwner (außer Adresse), nur dieser Kunde wird _license zugeordnet. Diese Funktion wird innerhalb der Funktion „newMcycleOwner“ ausgelöst, sodass sowohl Kunden als auch Zuordnungen gleichzeitig erstellt werden.

Wenn Sie dies auf diese Weise tun, müssen Sie jedoch zwei Datensätze mit den Informationen jedes Kunden haben, was wie eine Platzverschwendung erscheint, und auch wenn Kundeninformationen geändert werden müssen, müssen sie an zwei Stellen geändert werden. Gibt es einen besseren Weg, dies zu tun?

// < ---------------------- MOTORCYLCES ---------------------- >


mapping (address => Customer) mcycleowners;
address[] public mcycleownerAdds;


function newMcycleOwner(address _address, string _custname, string _color, string _make, uint32 _year, string _license) onlyMember public {

    Customer storage mcycleowner = mcycleowners[_address];
        mcycleowner.custname = _custname;
        mcycleowner.color = _color;
        mcycleowner.make = _make;
        mcycleowner.year = _year;
        mcycleowner.license = _license;

        mcycleownerAdds.push(_address);

    addLicense(_custname, _color, _make, _year, _license);
}

    function getMcycleAdds() public view returns(address[]) {
        return mcycleownerAdds;
    }

    function getMcycleByAdd(address _address) public view returns(string, string) {
        return (mcycleowners[_address].custname, mcycleowners[_address].license);
    }

    function countMcycle() public view returns(uint) {
        return mcycleownerAdds.length;
    }


// <---------- CREATION OF NEW MAP SO WE CAN QUERY BY LICENSE ---------->

//This seems to create two instances of each customer.  Replace with a better method.

mapping (string => Customer) mcyclelicenses;

function addLicense(string _custname, string _color, string _make, uint32 _year, string _license) onlyMember public {
    Customer storage mcyclelicense = mcyclelicenses[_license];
        mcyclelicense.custname = _custname;
        mcyclelicense.color = _color;
        mcyclelicense.make = _make;
        mcyclelicense.year = _year;

}

 function getMcycleByLic(string _license) public view returns(string, string, string, uint32) {
    return (mcyclelicenses[_license].custname, mcyclelicenses[_license].color, mcyclelicenses[_license].make, mcyclelicenses[_license].year);
}

Antworten (2)

Eine einfache Möglichkeit, dies zu tun, könnte darin bestehen, die Kundeninformationen in einem Array zu speichern und die Zuordnung zum Speichern der Indizes des Arrays zu verwenden, sodass Sie über die Zuordnung direkt auf den Index zugreifen und diesen Index verwenden, um direkt auf das Array zuzugreifen.

Hier ein Beispiel

pragma solidity ^0.4.23;

contract ContractX {
    struct Customer {
        string name;
        string license;
        /* other infos */
    }

    mapping (address => uint) addressIndexes;
    mapping (string => uint) licenseIndexes;
    Customer[] customers;
    uint customerCount;

    function addNewItem(address _address, string _name, string _license) public {
        customers.push(Customer(_name, _license));

        addressIndexes[_address] = customerCount;
        licenseIndexes[_license] = customerCount;

        customerCount++;
    }

    function getByAddress(address _address) public view returns(string, string) {
        return (
            customers[addressIndexes[_address]].name, 
            customers[addressIndexes[_address]].license
        );
    }

    function getByLicense(string _license) public view returns(string, string) {
        return (
            customers[licenseIndexes[_license]].name, 
            customers[licenseIndexes[_license]].license
        );
    }
}

Die Kundeninformationen wurden also nur einmal gespeichert und Sie verfolgen nur den Array-Index in das Mapping, damit Sie ihn später verwenden können, um direkt auf den gewünschten Kunden zuzugreifen.

CustomerEine andere Lösung könnte darin bestehen, den als Untervertrag zu verwenden , dann den Vertrag zu erstellen, wenn Sie Ihre Kundeninformationen hinzufügen, und die Adresse dieses neuen Vertrags in Ihren Zuordnungen zu speichern. Aber das öffnet ein anderes Szenario, und Sie müssen möglicherweise mehrere Änderungen vornehmen.

Ach, das ist großartig. Da Solidity noch recht neu ist, war mir noch nicht klar, dass ich bestimmte Elemente aus einem Array zurückgeben kann (nur dass ich das gesamte Array oder die Array-Länge zurückgeben kann). Ich werde das ausprobieren. Danke!

Sie können die Lizenz einfach einer Adresse zuordnen und dann zwei Suchen durchführen, um eine Lizenz zu dereferenzieren.

mapping(string => address) mcyclelicences;

function getMcycleByLic(string _license) public view returns(string, string, string, uint32) { 
  return (
    mcycleowners[mcyclelicenses[_license]].custname,
    mcycleowners[mcyclelicenses[_license]].color,
    mcycleowners[mcyclelicenses[_license]].make,
    mcycleowners[mcyclelicenses[_license]].year
  );      
}
Das ist ziemlich interessant und scheint eine großartige Abkürzung zu sein. Beides werde ich demnächst ausprobieren. Danke schön!