我是Gun的新手。我有现有的代码,可以根据模式非常有效地减少对象数组。我想我应该调整这个以在Gun' smap的上下文中运行,并为非匹配返回undefined。我想我还必须提供两个参数,其中一个是where子句,另一个是我希望在返回的对象上显示的属性。我还假设如果我使用.on未来的比赛会自动吐出来!我在正确的道路上吗?
const match = (object,key,value) => {
const type = typeof(value);
if(value && type==="object") {
return Object.keys(value).every(childkey =>
match(object[key],childkey,value[childkey]));
if(type==="function") return value(object[key]);
return object[key]===value;
}
const reduce = (objects,where) => {
const keys = Object.keys(where);
return objects.reduce((accumulator,current) => {
if(keys.every(key => match(current,key,where[key]))) {
accumulator.push(current);
}
return accumulator;
},[]);
}
let rows = reduce([{name: "Joe",address:{city: "Seattle"},age:25},
{name: "Mary",address:{city: "Seattle"},age:16},
{name: "Joe",address:{city: "New York"},age:20}],
{name: () => true,
address: {city: "Seattle"},
age: (age) => age > 10});
//结果 [{name:" Joe",地址:{city:" Seattle"},年龄:25}, {姓名:" Mary",地址:{city:" Seattle"},年龄:16}]
对此的进一步探索导致下面的代码在风格上有所不同,但符合Gun的即时响应特性。但是,目前还不清楚如何处理嵌套对象。下面的代码仅适用于基元。
const match = (object,key,value) => {
const type = typeof(value);
if(!object || typeof(object)!=="object") return false;
if(value && type==="object") {
const child = gun.get(object[key]["#"]);
for(let key in value) {
const value = {};
child.get(key).val(v => value[key] = v,{wait:0});
if(!match(value,key,value[key])) return;
}
}
if(type==="function") return value(object[key]);
return object[key]===value;
}
const gun = Gun(["http://localhost:8080/gun"]),
users = [{name: "Joe",address:{city: "Seattle"},age:25},
{address:{city: "Seattle"},age:25},
{name: "Mary",address:{city: "Seattle"},age:16},
{name: "Joe",address:{city: "New York"},age:20}];
//gun.get("users").map().put(null);
for(let user of users) {
const object = gun.get(user.name).put(user);
gun.get("users").set(object);
}
gun.get("users").map(user => {
const pattern = {name: (value) => value!=null, age: (age) => age > 20}; //, address: {city: "Seattle"}
for(let key in pattern) {
if(!match(user,key,pattern[key])) return;
}
return user;
}).on(data => console.log(data));
答案 0 :(得分:1)
是。 GUN的.map
method比看上去做得更多。
说我们有var users = gun.get('users')
。我们可以这样做:
users.map()
就像forEach
一样,因为默认回调是按原样返回数据。users.map(user => user.age * 2)
带有回调功能,可让您像map
一样转换数据,除非:{/ li>
users.map(function(){ return })
如果您返回undefined
,则会filter
删除该记录。警告:截至目前,
.map(transform)
功能目前尚未实验,而且我有错误。请尝试并报告您找到的任何内容。
现在我们可以将它与其他一些方法结合起来,以获得一些很酷的行为:
users.map().on(cb)
会将当前和未来的用户添加到表中,并获得有关每个用户的更新通知。users.map().val(cb)
会将当前和未来的用户添加到表中,但只会获得每个用户一次。users.val().map().on(cb)
只获取当前用户(不是将来),但会获得这些用户的更新。users.val().map().val(cb)
只获取当前用户(不是将来),只获取一次。是的,你走在正确的轨道上。例如,我在枪核中进行了测试:
list.map(user => user.age === 27? user.name + "thezombie" : u).on(function(data){
// verify
});
list.set({name: 'alice', age: 27});
list.set({name: 'bob', age: 27});
list.set({name: 'carl', age: 29});
list.set({name: 'dave', age: 25});
这会创建一个过滤结果的实时map
,并在本地(仅查看)转换数据。
将来,SQL和MongoDB Mango查询扩展将如何用于枪支。
注意:GUN仅加载您在对象/节点上请求的属性,因此它具有带宽效率。如果我们
users.map().get('age')
,它只会为每个用户加载年龄值,而不是其他任何内容。
在内部,您可以进行一些有效的检查,如果所有条件都匹配,则只/然后/加载整个对象。此外,还有另外两个选项:(1)您可以使用内存版本的枪来创建服务器端请求 - 响应模式,这样您就可以进行有效的服务器端过滤/查询。 (2)如果您成为适配器开发人员并学习简单的线规,然后编写自己的自定义查询语言扩展名!
还有别的吗?打我!非常乐意回答。
编辑:我在评论中回复,评论显然不能有代码。下面是如何“构建”更复杂查询的伪代码,这类似于SQL / Mango查询扩展将如何工作:mutli-value&嵌套值匹配可以从这个“构建”作为基础,但是,你是对的,直到我们有SQL / Mango查询示例,没有一个简单/立即“开箱即用”的例子。这是伪代码,但应该得到这个想法:
```
Gun.chain.match = function(query, cb){
var gun = this;
var fields = Object.keys(query);
var check = {};
fields.forEach(function(field){
check[field] = true;
gun.get(field).val(function(val){
if(val !== query[field]){ return }
check[field] = false;
//all checks done?
cb(results)
});
});
return gun;
}
```
答案 1 :(得分:0)
解决方案,诀窍是使用map
而非val
:
Gun.chain.match = function(pattern,cb) {
let node = this,
passed = true,
keys = Object.keys(pattern);
keys.every(key => {
const test = pattern[key],
type = typeof(test);
if(test && type==="object") {
node.get(key).match(test);
} else if(type==="function") {
node.get(key).map(value => {
if(test(value[key])) {
return value;
} else {
passed = false;
}
});
} else {
node.get(key).map(value => {
if(value[key]===test) {
return value;
} else {
passed = false;
}
});
}
return passed;
});
if(passed && cb) this.val(value => cb(value))
return this;
}
const gun = new Gun();
gun.get("Joe").put({name:"Joe",address:{city:"Seattle"},age:20});
gun.get("Joe").match({age: value => value > 15,address:{ city: "Seattle"}},value => console.log("cb1",value));