实时过滤json

时间:2016-06-21 02:39:49

标签: javascript json meteor

这个Meteor客户端应用程序"主要是智能手机使用"需要以键入文本的形式接受来自用户的输入并过滤大约500个底部节点的json数据,返回树的分支,其中底部节点文本包含用户输入文本。

{
  "people": {
    "honour": [
      [
        "family"
      ],
      [
        "friends"
      ]
    ],
    "respect": [
      [
        "one another"
      ]
    ]
  },
  "animals": {
    "eat": [
      [
        "row food"
      ]
    ]
  }
}

当用户输入' a'时,代码需要给出存在事件的树:

人,荣誉,家庭。
人,尊重,彼此

当用户键入' o'时,输出应为:
人,尊重,彼此 动物,吃,排食物。

当用户键入' oo'时,输出应为:
动物,吃,排食物。

当用户键入' f'时,输出应为:
人,荣誉,家庭 人,荣誉,朋友 动物,吃,排食物。

我的选择是:

  1. 将json转换为javascript对象,并使用少量循环编写seach / find / match逻辑。
  2. 使用我之前从未使用的defiantjs并且必须学习。
  3. 将json导入mongodb并过滤数据库。
  4. 无论你提出什么建议。
  5. 哪种最适合快速结果且易于维护?感谢

3 个答案:

答案 0 :(得分:1)

好的,这个问题是我创建通用Object方法Object.prototype.paths()以获取对象中所有路径的借口。在对象中有许多路径的值。在不同路径的末尾,某些值可能相同。我们将生成一个对象,其中原始对象的值为属性,这些属性为'价值观将成为道路。每个值可能有多个路径,因此是一个字符串数组,其中每个字符串数组将包含指向该值的单个路径。

因此,一旦我们使用此工具来映射对象值和路径,就可以很容易地获得结果。



Object.prototype.paths = function(root = [], result = {}) {
  var ok = Object.keys(this);
  return ok.reduce((res,key) => { var path = root.concat(key);
                                  typeof this[key] === "object" &&
                                         this[key] !== null ? this[key].paths(path,res)
                                                            : res[this[key]] == 0 || res[this[key]] ? res[this[key]].push(path)
                                                                                                    : res[this[key]] = [path];
                                  return res;
                                },result);
};

var data = {"people":{"honour":[["family"],["friends"]],"respect":[["one another"],["friends"]]},"animals":{"eat":[["row food"]]}},
   paths = data.paths(),
  values = Object.keys(paths),
  keystr = document.getElementById("keystr");
getPaths = function(str){
	var valuesOfInterest = values.filter(f => f.includes(str));
	return valuesOfInterest.reduce((p,c) => p.concat({[c]: paths[c]}),[]);
};
keystr.oninput = function(e){
                   console.log(JSON.stringify(getPaths(e.target.value),null,2))
                 }

<input id="keystr" placeholder = "enter some characters" value = ""/>
&#13;
&#13;
&#13;

所以当你按下&#34; o&#34;你会得到以下

[
  {
    "one another": [
      [
        "people",
        "respect",
        "0",
        "0"
      ]
    ]
  },
  {
    "row food": [
      [
        "animals",
        "eat",
        "0",
        "0"
      ]
    ]
  }
]

这意味着:

  • 外部数组有2个对象项。这意味着在原版中 对象有两个值&#34; o&#34;其中的角色。 &#34;彼此&#34;和#34;排食&#34;,
  • &#34;彼此&#34;只有一条路径["people", "respect", "0", "0"]。如果&#34;彼此&#34;被列在多个地方,如&#34;朋友&#34;在&#34;尊重&#34;并且&#34;荣誉&#34;那么这个数组将包含两个带路径的子数组。输入&#34; fr&#34;并亲自看看。

几句警告:我们在使用Object原型时应该谨慎。我们的修改应该有描述符enumerable = false或者它将在for in循环中列出,例如jQuery将不起作用。 (这是jQuery的愚蠢,因为显然他们没有在for循环中进行hasOwnProperty检查。一些好的读取是herehere所以我们必须添加这个Object方法使用Object.defineProperty()将其设为enumerable = false;。但是为了简单起见并且仍然在问题的范围内,我还没有在代码中包含该部分。

答案 1 :(得分:0)

我认为一些循环可以正常工作。在下面的示例中,当您在输入中键入时,与搜索匹配的结果将记录到控制台。

$("#search").on("input", function() {
  var result = [];
  var search = this.value;

  if (search.length) {
    $.each(data, function(key1, value1) {
      //key1: people, animals
      $.each(value1, function(key2, value2) {
        //key2: honor, respect, eat
        $.each(value2, function(i, leaf) {
          if (leaf.length && leaf[0].indexOf(search) >= 0) {
            //found a match, push it onto the result
            var obj = {};
            obj[key1] = {};
            obj[key1][key2] = leaf;
            result.push(obj);
          }
        });
      });
    });
  }

  console.log(result);
});

var data = {
  "people": {
    "honour": [
      [
        "family"
      ],
      [
        "friends"
      ]
    ],
    "respect": [
      [
        "one another"
      ]
    ]
  },
  "animals": {
    "eat": [
      [
        "row food"
      ]
    ]
  }
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input id="search" />

答案 2 :(得分:0)

使用此程序包进行meteor很棒https://atmospherejs.com/matteodem/easy-search