【问题标题】:Live filtering of jsonjson的实时过滤
【发布时间】:2016-06-22 05:26:04
【问题描述】:

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

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

当用户输入'a'时,代码需要给出出现的树:

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

当用户输入“o”时,输出应该是:
人,尊重,彼此。
动物,吃,排食物。

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

当用户输入“f”时,输出应该是:
人、荣誉、家庭。
人,荣誉,朋友。
动物,吃,排食物。

我的选择是:

  1. 将 json 转换为 javascript 对象,并使用少量循环编写搜索/查找/匹配逻辑。
  2. 使用defiantjs,我以前从未使用过,必须学习。
  3. 将json导入mongodb并过滤数据库。
  4. 您还有什么建议。

哪种方法最适合快速获得结果且易于维护?谢谢

【问题讨论】:

  • 这个对象可以包含多少个键?几十、几百、几千?
  • 哎呀,没关系。错过了 500 个节点线。
  • 为什么不把JSON文件的结构倒过来呢?把最后一个搜索词放在前面,然后你只需要搜索第一层而不是递归地深入三层。它可能会产生更大的文件,重复次数更多,但会提高性能。 (无论您选择哪种方式,我都看不到您当前的实现是高性能的)
  • honour 下有一个数组,每个数组都有一个项目。这是否应该是我们应该只是一个字符串数组?如果是前者,那么当叶子节点中有多个项目时,它应该如何表现?
  • @dave 是的。没错,有数组,它们有不同数量的输入。我再举一个例子来回答你的第二个问题。

标签: javascript json meteor


【解决方案1】:

好的,这个问题是我创建通用对象方法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 = ""/>

所以当你按“o”时,你会得到以下信息

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

这意味着:

  • 外部数组有 2 个对象项。这意味着在原 对象中有两个带有“o”字符的值。 “彼此”和“排食物”,
  • “彼此”只有一个路径["people", "respect", "0", "0"]。如果“彼此”被列在多个位置,例如“朋友”,“尊重”和“荣誉”下都列出了,那么这个数组将包含两个带有路径的子数组。输入“fr”并亲自查看。

几句警告:我们在玩 Object 原型时应该小心。我们的修改应该有enumerable = false 的描述符,否则它将在for in 循环中列出,例如jQuery 将不起作用。 (这就是 jQuery 的愚蠢之处,因为显然他们没有在他们的 for in 循环中进行hasOwnProperty 检查)一些不错的读物是herehere 所以我们必须添加这个带有Object.defineProperty() 的Object 方法来制作它enumerable = false;。但是为了简单起见并保持在问题的范围内,我没有在代码中包含该部分。

【讨论】:

  • @Fred J. OK 现在它允许您输入字母并立即返回相关对象。
【解决方案2】:

我认为几个循环就可以了。在下面的示例中,当您输入输入内容时,与您的搜索匹配的结果将记录到控制台。

$("#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" />

【讨论】:

    【解决方案3】:

    为流星使用这个包很棒https://atmospherejs.com/matteodem/easy-search

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-12
      • 2022-01-20
      • 2011-03-25
      • 1970-01-01
      • 2017-12-09
      相关资源
      最近更新 更多