Suchen Sie nach Daten zu einem Smart Contract?

Ich habe einen intelligenten Vertrag, der einige Artikeldaten enthält, die in einer Struktur gespeichert sind, die einer ID zugeordnet ist, die sie eindeutig mit einer Zuordnung identifiziert, wie folgt:

struct Foo {
    string a;
    string b;
}

mapping (uint64 => Foo) public articles;

(Offensichtlich ist der obige Code vereinfacht, aber die Struktur ist dieselbe, obwohl die echte Struktur 7 Variablen anstelle von 2 hat).

Jetzt muss ich in der Lage sein, mit einem der 7 Attribute zu suchen. Die Blockchain wird privat sein, daher ist der Gasverbrauch kein Problem.

Meine erste Lösung bestand darin, dem Smart Contract eine Suchmethode hinzuzufügen und darin das gesamte Mapping zu durchlaufen und zu prüfen, welche Elemente die Bedingung erfüllen. Offensichtlich ist dies O (n) und es dauerte ungefähr 8 Sekunden für 2000 Elemente, was zwar nicht schlecht ist, aber ich hoffe auf eine bessere Lösung.

Dann dachte ich darüber nach, 7 weitere Zuordnungen zu haben, die als Suchindizes fungieren und jeden Attributwert dem Index des Artikels zuordnen würden, der ihn erfüllt, wie zum Beispiel:

mapping (string => uint64) public searchIndex;

(Beachten Sie, dass es im Moment nicht erforderlich ist, Teilzeichenfolgen zu überprüfen, sondern nur Gleichheit.)

Und schließlich habe ich darüber nachgedacht, ob es gut wäre, diese Indizes auf Elastic Search statt auf der Blockchain selbst zu halten, obwohl ich, wenn möglich, eine reine Blockchain-basierte Lösung bevorzugen würde.

Welche dieser Optionen (von allen anderen, die Sie besser kennen) halten Sie für angemessener?

Danke dir.

Ist diese Open-Source-Suchmaschine für intelligente Verträge mit M2M-API von Interesse? blog.secondstate.io/post/20190703-search-engine-overview ethereum.search.secondstate.io

Antworten (2)

Es ist klar, dass Sie das gewünschte Objekt nicht direkt erhalten können, ohne seinen Schlüssel zu kennen. Die Idee der 7 Mappings ist eigentlich die naheliegendste und am wenigsten komplizierte und funktioniert in den meisten Fällen nicht nur bei Ihnen.

Die nützlichste Idee, die mir einfällt, ist, dass Sie in Ihren Strukturattributen nach Mustern suchen, Muster, die Ihnen helfen, ein Suchschema zu organisieren, falls Sie 10 oder 20.000 Elemente haben. z.B ; wenn string aWerte mit einem bekannten Zeitstrahl wie a == "X12"für heute verknüpft sind und am nächsten Tag ein weiterer Eintrag hätte a == "X13". Wenn Sie also nach Strukturen mit suchen möchten, a == X32haben Sie ein besseres Verständnis dafür, wo sich diese Struktur befinden könnte und was die Suchindexgrenzen sind.

So wird die Suche in 20.000 Elementen zu einer Suche in nur 2.000.

hoffe es war klar.

Eine Sache, die ich getan habe, um diese Art von Problem zu lösen, besteht darin, die Daten, die in den Vertrag eingehen, in einer Redis- oder Mongo-Datenbank zu spiegeln, um einen viel besser abfragbaren Datensatz zu erstellen. Wenn ich dann diese Datenbank abfrage, verifiziere ich die Daten in der Blockchain mit einer Getter-Funktion, um sicherzustellen, dass sie nicht manipuliert wurden. Mir ist klar, dass dies nicht die reinste reine Blockchain-Methode ist, aber es funktioniert, ohne gaslastige Schleifen oder mehrere Karten zu riskieren, die die Speicherkosten für einfache Abfragen zu Nicht-Schlüsselattributen vervielfachen.

Angesichts Ihres vereinfachten Vertrags:

struct Foo {
    string a;
    string b;
}

mapping (uint64 => Foo) public articles;

Sie können ein Ereignis erstellen, das immer dann ausgegeben wird, wenn ein neuer Zusatz wie folgt erstellt wird, der die Werte und die eindeutige ID zurückgibt:

event newArticleCreated(string a, string b, index uint64);

Dann können Sie mit der Ethers.js-Bibliothek (oder einer anderen wie Web3) einen Listener einrichten, um alle Instanzen dieses Ereignisses abzufangen und die Daten von dort aus wie gewünscht zu verarbeiten. In diesem Fall würden Sie die Daten an einen Dienst weitergeben, der die Daten zu Mongo oder Redis hinzufügt, wobei der Schlüssel der uint64-Schlüssel in Ihrem Vertrag ist:

    //import the ethers.js library
    const ethers = require('ethers');

    //set your provider and create a new instance of your contract by providing 
    //the ABI and deployed address 
    let provider = new ethers.providers.JsonRpcProvider(<RPC URL for your node>); 
    contractInstance = new ethers.Contract(<contractAddress>, <abi>, provider);

    //listen for events matching this name
    contractInstance.on("newArticleCreated", (a, b, index) => {
        //do stuff when the event fires

        //set the values in the event to a JSON object structure
        let chainObj = {
            id: index, 
            a: a
            b: b
        }

        //add the data to the database
        dataService.addDataToDatabase(chainObj);

Ich hatte persönlich Erfolg mit dieser Art von Setup und es hat viel Flexibilität. Es ermöglicht Ihnen, Daten abzufragen, die von der Kette gespiegelt werden, aber diese Daten immer mit dem Vertrag unter Verwendung dieses Index/dieser eindeutigen ID zu verifizieren.

Vielen Dank!