繁体   English   中英

如何在文档中查询 Firestore 搜索名称?

[英]How to query a firestore search for a name within a document?

我为我的 firestore 数据库设置的是一个名为“funkoPops”的集合。 其中包含 funkoPops 类型的文档,以及包含该类型所有流行音乐的 funkoData 数组。 它看起来像下面这样


我还应该注意,funkoPops 集合有数百个“流派”文档,这基本上是 funko pop 系列,我 web 抓取了 funkoData 的子 collections,现在需要能够搜索“funkoData”的数组字段将名称字段与给定的搜索参数匹配。

collection: funkoPops => document: 2014 Funko Pop Marvel Thor Series => fields: funkoData: [ 
{
  image: "string to hold image",
  name: "Loki - with helmet",
  number: "36"
},
{
  image: "string to hold image",
  name: "Black and White Loki with Helmet - hot topic exsclusive",
  number: "36"
},
{
etc...
}

那么我如何在 firestore 中运行查询以便能够在集合中搜索('funkoPops'),在文档字段中搜索名称。

我有能力像这样搜索流派,这会返回流派和带有以下数据数组的文档:

const getFunkoPopGenre = async (req, res, next) => {
  try {
    console.log(req.params);
    const genre = req.params.genre;
    const funkoPop = await firestore.collection("funkoPops").doc(genre);
    const data = await funkoPop.get();
    if (!data.exists) {
      res.status(404).send("No Funko Pop found with that search parameter");
    } else {
      res.send(data.data());
    }
  } catch (error) {
    res.status(400).send(error.message);
  }
};

我试图用来按字段名称搜索的内容如下并返回一个空 obj:

const getFunkoPopName = async (req, res, next) => {
  try {
    const name = req.params.name;
    console.log({ name });
    const funkoPop = await firestore
      .collection("funkoPops")
      .whereEqualTo("genre", name);
    const data = await funkoPop.get();
    console.log(data);
    res.send(data.data());
  } catch (error) {
    res.status(400).send(error);
  }
};

任何帮助都会很棒,谢谢!

所以我回答这个问题的方式似乎来自顶级评论,并在 firebase 上进行了更多研究,你是否必须匹配一个完整的字符串才能使用 firebase 查询进行搜索。 相反,我查询集合中的所有文档,将其添加到数组中,然后 forEach() 每个 funkoData。 然后我从那里创建一个 matchArray 和 go forEach() 通过我从第一个查询中获得的新 funkoData 数组。 然后在那个 forEach() 里面我有一个新的变量,它是数据数组的过滤器,将数据字段名称与.inlcudes(search param) 匹配,然后将所有匹配项推送到 matchArr 和 res.send(匹配Arr)。 适用于部分字符串以及 .includes() 匹配完整和 substring。 不确定这是否是最好和最有效的方法,但我能够在 1-2 秒内查询大约 20k 数据并找到所有匹配项。 代码看起来像这样

try {
    const query = req.params.name.trim().toLowerCase();
    console.log({ query });
    const funkoPops = await firestore.collection("test");
    const data = await funkoPops.get();
    const funkoArray = [];
    if (data.empty) {
      res.status(404).send("No Funko Pop records found");
    } else {
      data.forEach((doc) => {
        const funkoObj = new FunkoPop(doc.data().genre, doc.data().funkoData);
        funkoArray.push(funkoObj);
      });
      const matchArr = [];
      funkoArray.forEach((funko) => {
        const genre = funko.genre;
        const funkoData = funko.funkoData;
        const matches = funkoData.filter((data) =>
          data.name.toLowerCase().includes(query)
        );
        if (Object.keys(matches).length > 0) {
          matchArr.push({
            matches,
            genre,
          });
        }
      });
      if (matchArr.length === 0) {
        res.status(404).send(`No Funko Pops found for search: ${query}`);
      } else {
        res.send(matchArr);
      }
    }
  } catch (error) {
    res.status(400).send(error.message);
  }

稍作调整,我就可以在我的数据库中搜索任何字段,并将其与完整字符串和 substring 匹配。

更新

最终只是将类型、名称和数字搜索组合到一个 function 中,这样当有人搜索时,查询参数将同时用于所有 3 个搜索,并将所有 3 个搜索的数据作为 object 返回,这样我们就可以做任何我们想做的事情就像在前端:

const getFunkoPopQuery = async (req, res) => {
  try {
    console.log(req.params);
    const query = req.params.query.trim().toLowerCase();
    const funkoPops = await firestore.collection("test");
    const data = await funkoPops.get();
    const funkoArr = [];
    if (data.empty) {
      res.status(404).send("No Funko Pop records exsist");
    } else {
      data.forEach((doc) => {
        const funkoObj = new FunkoPop(doc.data().genre, doc.data().funkoData);
        funkoArr.push(funkoObj);
      });

      // genre matching if query is not a number
      let genreMatches = [];
      if (isNaN(query)) {
        genreMatches = funkoArr.filter((funko) =>
          funko.genre.toLowerCase().includes(query)
        );
      }
      if (genreMatches.length === 0) {
        genreMatches = `No funko pop genres with search: ${query}`;
      }

      // name & number matching
      const objToSearch = {
        notNullNameArr: [],
        notNullNumbArr: [],
        nameMatches: [],
        numbMatches: [],
      };

      funkoArr.forEach((funko) => {
        const genre = funko.genre;
        if (funko.funkoData) {
          const funkoDataArr = funko.funkoData;
          funkoDataArr.forEach((data) => {
            if (data.name) {
              objToSearch.notNullNameArr.push({
                funkoData: [data],
                genre: genre,
              });
            }
            if (data.number) {
              objToSearch.notNullNumbArr.push({
                funkoData: [data],
                genre: genre,
              });
            }
          });
        }
      });
      // find name that includes query
      objToSearch.notNullNameArr.forEach((funko) => {
        const genre = funko.genre;
        const name = funko.funkoData.filter((data) =>
          data.name.toLowerCase().includes(query)
        );
        if (Object.keys(name).length > 0) {
          objToSearch.nameMatches.push({
            genre,
            name,
          });
        }
      });
      // find number that matches query
      objToSearch.notNullNumbArr.forEach((funko) => {
        const genre = funko.genre;
        const number = funko.funkoData.filter((data) => data.number === query);
        if (Object.keys(number).length > 0) {
          objToSearch.numbMatches.push({
            genre,
            number,
          });
        }
      });

      if (objToSearch.nameMatches.length === 0) {
        objToSearch.nameMatches = `No funko pops found with search name: ${query}`;
      }
      if (objToSearch.numbMatches.length === 0) {
        objToSearch.numbMatches = `No funko pop numbers found with search: ${query}`;
      }

      const searchFinds = {
        genre: genreMatches,
        name: objToSearch.nameMatches,
        number: objToSearch.numbMatches,
      };

      res.send(searchFinds);
    }
  } catch (error) {
    res.status(400).send(error.message);
  }
};

如果有人非常适合后端并了解有关 Firestore 查询的更多信息,请告诉我!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM