我有一个智能契约,它包含存储在结构中的一些文章数据,它使用一个id映射,该id唯一地将其标识为映射,如下所示:
struct Foo {
string a;
string b;
}
mapping (uint64 => Foo) public articles;(很明显,上面的代码很简单,但是结构是相同的,尽管真正的结构有7个变量而不是2个)。
现在我必须能够使用这7个属性中的任何一个进行搜索。区块链将是私有的,因此天然气的使用并不是一个问题。
我的第一个解决方案是向智能契约中添加一个搜索方法,并在其中遍历整个映射并检查哪些项满足条件。很明显,这是O(n),2000元素花费了大约8秒,虽然还不错,但我希望有一个更好的解决方案。
然后,我考虑让更多的映射充当搜索索引,将每个属性值映射到满足它的文章的索引,例如:
mapping (string => uint64) public searchIndex;(注意,现在它不需要检查子字符串,只需要相等)
最后,我在考虑是否应该将这些索引保存在弹性搜索中,而不是在区块链本身上,尽管如果可能的话,我更喜欢基于块链的解决方案。
那么,你认为这些选项(你知道的其他更好的)是否更合适呢?
谢谢。
发布于 2018-02-16 08:23:46
很明显,在不知道关键的情况下,你不能直接得到你想要的对象。这7个映射的想法实际上是最明显和最简单的一个,它在大多数情况下起作用,而不仅仅是你的。
我能想到的最有用的想法是,您可以在struct属性中查找模式,这种模式可以帮助您组织一个搜索模式,以防您有10或2万个元素。如果string a值链接到一个已知的时间线,比如今天和第二天的a == "X12",那么另一个条目将有a == "X13"。因此,当您想使用a == X32搜索结构时,您将更好地了解该结构的位置以及搜索索引的限制。
因此,在两万种元素中进行搜索,只能在2000种元素中进行搜索。
希望一切都很清楚。
发布于 2020-02-05 16:38:26
为了解决同样的问题,我所做的一件事就是在Redis或Mongo数据库中镜像合同中的数据,以创建一个更可查询的数据集。然后,每当我查询该数据库时,我就使用getter函数验证块链中的数据,以确保它没有被篡改。我意识到这并不是最纯粹的区块链方法,但它的工作原理是不冒重气循环的风险,也不需要多个映射来增加存储成本,这样就可以对非键属性进行简单的查询。
考虑到你的简化合同:
struct Foo {
string a;
string b;
}
mapping (uint64 => Foo) public articles;每当创建这样的新添加时,您可以创建一个要发出的事件,返回值和唯一ID:
event newArticleCreated(string a, string b, index uint64);然后,使用Ethers.js库(或其他类似于Web3的库),您可以设置一个侦听器来捕获该事件的任何实例,并根据您的意愿处理数据。在这种情况下,您可以将数据传递给一个将数据添加到Mongo或Redis的服务,该服务的密钥是您合同中的uint64密钥:
//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);我个人在这种类型的设置中取得了成功,而且它有很大的灵活性。它允许您查询来自链的镜像数据,但始终使用该索引/唯一ID验证该数据与契约一起返回。
谢谢!
https://ethereum.stackexchange.com/questions/39825
复制相似问题