使用 JS,如何实现电子商务风格的分面搜索,以及一系列本身是嵌套值的可能条件

Using JS, how to implement an e-commerce style faceted search, with an array of possible criteria which are themselves nested values

我经常在电子商务网站上看到的是带有用于各种过滤值的复选框的边栏。其中许多都可以检查,添加新值可以进一步缩小搜索范围。

我想为与数字媒体有关的元数据实现类似的功能。我有一组可能的过滤器,每个过滤器都是一个对象 {nameOfProperty: ['Value1', 'Value2']}。这个想法是 return 结果满足属性数组 {value: 'Value1', trait_type: 'NameOfProperty'}.

中的所有条件

参见示例:

const arr = [
  { metadata: { json: { 
    attributes: [
      { value: "Copycat Fridge Artist", trait_type: "Artist" },
      { value: "Fridges Vol. 2", trait_type: "Playlist" },
      { value: "Fridges Playlist", trait_type: "Playlist" },
      { value: "Image", trait_type: "Artwork Type" }
    ]
  },

  { metadata: { json: { 
    attributes: [
      { value: "Copycat Fridge Artist", trait_type: "Artist" },
      { value: "Fridges Vol. 1", trait_type: "Collection" },
      { value: "Videos Playlist", trait_type: "Playlist" },
      { value: "Video", trait_type: "Artwork Type" }
    ]
  },

  { metadata: { json: { 
    attributes: [
      { value: "Cool Original Artist", trait_type: "Artist" },
      { value: "Fridges Vol. 1", trait_type: "Collection" },
      { value: "Videos Playlist", trait_type: "Playlist" },
      { value: "Video", trait_type: "Artwork Type" }
    ]
  }
];

和一组过滤器

filters: [{Artwork Type: ['Image', 'Video']},
          {Playlist: ['Videos Playlist']},
          {Artist: ['Cool Original Artist']}]

在这种情况下,我想查看图像 视频, 来自视频播放列表,然后 出自 Cool Original Artist 之手。过滤器应该 return arr[2].

过滤器可以多种多样,并不是数组中的每一项都具有名称属性数。

如果有这种 search/filter 的名称,我不知道,如果之前有人问过这个问题,我们深表歉意。这是我遇到过很多次的事情,但从未尝试过自己编写代码,我正在苦苦挣扎!

通常我会过滤减速器中的 arr 值。

const arr = [
  { metadata: { json: { 
    attributes: [
      { value: "Copycat Fridge Artist", trait_type: "Artist" },
      { value: "Fridges Vol. 2", trait_type: "Playlist" },
      { value: "Fridges Playlist", trait_type: "Playlist" },
      { value: "Image", trait_type: "Artwork Type" }
    ]
  }}},

  { metadata: { json: { 
    attributes: [
      { value: "Copycat Fridge Artist", trait_type: "Artist" },
      { value: "Fridges Vol. 1", trait_type: "Collection" },
      { value: "Videos Playlist", trait_type: "Playlist" },
      { value: "Video", trait_type: "Artwork Type" }
    ]
  }}},

  { metadata: { json: { 
    attributes: [
      { value: "Cool Original Artist", trait_type: "Artist" },
      { value: "Fridges Vol. 1", trait_type: "Collection" },
      { value: "Videos Playlist", trait_type: "Playlist" },
      { value: "Video", trait_type: "Artwork Type" }
    ]
  }}}
];

const filters = [
  { "Artwork Type": ["Image", "Video"] },
  { Playlist: ["Videos Playlist"] },
  { Artist: ["Cool Original Artist"] }
];

// reduce the arr by matching with each filter object
const result = filters.reduce((remaining, curr) => {

  // assign filter attribute name and values
  const [name, values] = Object.entries(curr)[0];
  
  // do filtering
  return remaining.filter(({metadata: { json: {attributes}}}) =>
    attributes.find((a) => a.trait_type === name && values.includes(a.value))
  );
}, arr);

console.log(result);