使用地图减少枪支

时间:2017-05-22 21:04:57

标签: gun

我是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));

2 个答案:

答案 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));