【问题标题】:Search function from JSON structure从 JSON 结构中搜索功能
【发布时间】:2021-02-09 09:45:05
【问题描述】:

我正在寻找基于搜索字段中的用户输入来搜索 JSON 值的解决方案。

例如:如果用户在 ASD 中键入,则 Json 值中包含 ASD 的任何数据都应显示。

我找到了一个例子,它就像我想要的那样工作。但是,它们没有使用 JSON 结构。

这是我遵循的代码: App.svelte:

<script>
    import Search from "./Search.svelte";
    
      const data = [
    "Metrics Server",
    "Node.js",
    "Virtual Machine",
    "Virtual Private Server",
  ];
</script>

<Search autofocus {data} let:filtered>
  <ul>
    {#each filtered as item}
    <li>{item}</li>
    {/each}
  </ul>
</Search>

Search.svelte

<script>
import {onMount} from "svelte";
export let autofocus = false;
export let data = [];

let input = undefined;
let value ="";

onMount(() =>{
    if(autofocus) {
        input.focus();
    }
});

$: filtered = data.filter((item) => 
    item.toLowerCase().includes(value.toLowerCase()));
 </script>
<style>
ul{
    list-style:none;
}
</style>
<input bind:this="{input}" type="search" bind:value />


<ul>
{#each filtered as item}
<li>{item}</li>
{/each}
</ul>

此代码不适用于 JSON 结构,例如: {"name": "tommy, "class":"a"}, {"name": "dummy, "class":"b"} ...

它会返回如下错误:

item.toLowerCase is not a function

如何实现一个搜索功能,如果用户搜索“tommy”,它将返回我的名字

这就是我检索 Json 数据的方式:

let info ="";
onMount(async () =>{
     const resp = await fetch('https:xx.xxx.xxx')
        info = await resp.json();      
    });

我得到的数据是这种格式:[编辑]

[    {
    "table_schema": "x",
    "table_name": "a",
    "column_name": "typname",
    "data_type": "name",
    "character_maximum_length": null
},
{
    "table_schema": "b",
    "table_name": "x",
    "column_name": "typnamespace",
    "data_type": "oid",
    "character_maximum_length": null
}]

我已经编辑了我的真实 JSON 文件。该代码确实适用于我的虚拟 JSON,但不适用于真正的 JSON。有什么想法吗?

【问题讨论】:

  • 你是否有一个对象数组,例如data = [{ name: 'tommy', class: 'a' }, { name: 'eric', class: 'b' }]?
  • 是的。我实际上是使用 fetch 函数从数据库中获取数据。我将用我的代码编辑我的帖子供您参考

标签: arrays json function search svelte


【解决方案1】:

您必须遍历项目的每个属性并比较它们:

  • 首先循环使用data.filter 的项目
  • 获取每个物品的所有道具Object.keys(item)
  • 检查是否至少有一个匹配条件.some
  • 比较item中的key和值item[key].toLower....
$: filtered = data.filter(item => 
   Object.keys(item).some(key => 
     item[key].toLowerCase().includes(value.toLowerCase())
   )
);

请注意,此代码假定数组中的所有项都是对象,如果您在对象和字符串之间混合使用,它将失败:

[ "Tommy", { name: "Sammy" }]

这里的第一个元素并没有真正的“键”。您必须先为此添加额外的检查。

【讨论】:

  • 嗨斯蒂芬!感谢你的帮助。我还没有尝试过这个。如果我遇到任何困难,我会让你,如果它有效,我会投票给你的答案。我已经编辑了我的代码。该数组是否适用于此代码?
  • 该代码将适用于您粘贴的数组,但请注意,它将检查 所有 属性是否匹配,而不仅仅是名称
  • 嗨斯蒂芬,代码有效!但是,如果 JSON 值采用字符串格式,则该代码有效。但是,如果我将 null 作为值,则它不起作用。您知道如何解决此问题以及如何使用不同的键进行搜索吗?非常感谢
  • 要覆盖空值,您必须扩展进行实际比较的部分以处理这些情况,一个简单的if 应该能够做到这一点。如果您只想搜索特定键,您可以跳过整个Object.keys 部分,直接检查键是否?
  • 现在我收到错误,例如:“Search.svelte:23 Uncaught (in promise) TypeError: Cannot read property 'toLowerCase' of null at Search.svelte:23 at Array.some () 在 Search.svelte:22 在 Array.filter () 在 Object.$$self.$$.update (Search.svelte:21) 在更新 (index.mjs:726) 在刷新 (index. mjs:699)"