部分时间对社交媒体类型网络应用程序的搜索实现

Search implementation to social media type web app working part of the time

我正在尝试制作一个社交媒体类型的应用程序,目前正在尝试实现一个搜索功能以便能够找到朋友。我有下面的代码,它有时工作而其他时候不工作(真的很令人沮丧!)我很确定这与 javascript 的异步性质有关。我想我可以通过将第二个 find 放在 then 函数中来解决这个问题。代码应该搜索以检查用户的名字,然后搜索用户的姓氏并将其推送到一个名为 users 的数组中,然后将其展平并编辑为仅具有唯一的用户对象。然后将其传递给显示用户的车把。问题似乎来自以下测试,这些测试处理多个单词,有时搜索第二个单词,有时不搜索:

  1. 用户搜索 returns 每个词的结果
  2. 搜索不受添加非字母数字字符的影响

控制器

const User = require("../models/user");

const SearchController = {
  Index: (req, res) => {
    const users = [];
    User.find().then((user) => {
      users.push(user);
      const merged = [].concat.apply([], users);
      const uniqueArray = merged.filter((value, index) => {
        const _value = JSON.stringify(value);
        return (
          index ===
          merged.findIndex((obj) => {
            return JSON.stringify(obj) === _value;
          })
        );
      });
      res.render("search/index", { users: uniqueArray });
    });
  },
  Create: (req, res) => {
    const searchArray = req.body.message.replace(/[\W_]+/g, " ").split(/[ ,]+/);

    const users = [];
    searchArray.forEach((name) => {
      User.find({
        firstName: { $regex: name, $options: "i" },
        // lastName: { $regex: name, $options: "i" },
      }).then((user) => {
        users.push(user);
        User.find({
          // firstName: { $regex: name, $options: "i" },
          lastName: { $regex: name, $options: "i" },
        }).then((user) => {
          users.push(user);
          const merged = [].concat.apply([], users);
          const uniqueArray = merged.filter((value, index) => {
            const _value = JSON.stringify(value);
            return (
              index ===
              merged.findIndex((obj) => {
                return JSON.stringify(obj) === _value;
              })
            );
          });
          res.render("search/index", { users: uniqueArray });
        });
      });
    });
  },
};

module.exports = SearchController;

赛普拉斯测试

describe("Searching users", () => {
  beforeEach(() => {
    cy.signUp();
    cy.signUp("Chris", "Coding", "chris@coding.com", "12345");
    cy.signUp("Paul", "Coding", "paul@coding.com", "12345");
    cy.signUp("Adam", "Woodcock", "adam@woodcock.com", "12345");
    cy.signUp("Kathleen", "Woodcock", "kathleen@woodcock.com", "12345");
    cy.signUp("George", "Hett", "george@hett.com", "12345");
    cy.signUp("Rob", "Oman", "rob@oman.com", "12345");
  });

  it("A user can search for other users", () => {
    cy.login();
    cy.get("#searchBox").type("george");
    cy.get("#searchButton").click();

    cy.get(".user-container").first().should("contain", "George Hett");
  });

  it("A user can search for other users by last name", () => {
    cy.login();
    cy.get("#searchBox").type("woodcock");
    cy.get("#searchButton").click();

    cy.get(".user-container").should("have.length", 2);
    cy.get(".user-container").should("contain", "Adam Woodcock");
    cy.get(".user-container").should("contain", "Kathleen Woodcock");
  });

  it("A blank search returns all users", () => {
    cy.login();
    cy.get("#searchButton").click();

    cy.get(".user-container").should("have.length", 7);
    cy.get(".user-container").should("contain", "Adam Woodcock");
    cy.get(".user-container").should("contain", "Kathleen Woodcock");
    cy.get(".user-container").should("contain", "Chris Coding");
    cy.get(".user-container").should("contain", "Paul Coding");
    cy.get(".user-container").should("contain", "Rob Oman");
    cy.get(".user-container").should("contain", "George Hett");
    cy.get(".user-container").should("contain", "Barry Barry-Barroldsson");
  });

  it("Visiting the search page without going through the search bar returns all users", () => {
    cy.login();
    cy.visit("/search");

    cy.get(".user-container").should("have.length", 7);
    cy.get(".user-container").should("contain", "Adam Woodcock");
    cy.get(".user-container").should("contain", "Kathleen Woodcock");
    cy.get(".user-container").should("contain", "Chris Coding");
    cy.get(".user-container").should("contain", "Paul Coding");
    cy.get(".user-container").should("contain", "Rob Oman");
    cy.get(".user-container").should("contain", "George Hett");
    cy.get(".user-container").should("contain", "Barry Barry-Barroldsson");
  });

  it("A search is not affected by adding non alphanumeric characters", () => {
    cy.login();
    cy.get("#searchBox").type("Chris   /.,[]   Coding");
    cy.get("#searchButton").click();

    cy.get(".user-container").should("have.length", 2);
    cy.get(".user-container").should("contain", "Chris Coding");
    cy.get(".user-container").should("contain", "Paul Coding");
  });

  it("A user's search returns results for each word", () => {
    cy.login();
    cy.get("#searchBox").type("Chris Woodcock");
    cy.get("#searchButton").click();

    cy.get(".user-container").should("have.length", 3);
    cy.get(".user-container").should("contain", "Adam Woodcock");
    cy.get(".user-container").should("contain", "Kathleen Woodcock");
    cy.get(".user-container").should("contain", "Chris Coding");
  });
});

请您推荐我可以进行哪些调整以使此代码正常运行

你可能会发现这个效果更好,虽然我找不到任何容易因异步处理而失败的东西。

我假设 User.find() returns 一个承诺。

const promises = searchArray.map((name) => {
  return User.find({
    firstName: { $regex: name, $options: "i" },
    lastName: { $regex: name, $options: "i" },
  })
})

Promise.all(promises).then((values) => {
  const uniqueArray = values
    .flat()
    .filter((value, index, arr) => arr.indexOf(value) === index)
  res.render("search/index", { users: uniqueArray });
})

cy.get(".user-container").should("have.length", 3); 应该处理测试结束时的任何滞后,但如果执行 multi-level 搜索可能需要超过 4 秒,您可能希望增加超时。

cy.get(".user-container", {timeout:10000})
  .should("have.length", 3);

我通过将上面的内容重构为这个,通过更改 for each 循环来构建最终查询并将其传递给 find 语句,然后渲染效果非常好,从而设法解决了我自己的问题。我还重构了索引路由。

const User = require("../models/user");

const SearchController = {
  Index: (req, res) => {
    User.find().then((users) => {
      res.render("search/index", { users: users });
    });
  },
  Create: (req, res) => {
    const searchArray = req.body.message.replace(/[\W_]+/g, " ").split(/[ ,]+/);
    const findQuery = [];
    searchArray.forEach((name) => {
      const first = { firstName: { $regex: name, $options: "i" } };
      const second = { lastName: { $regex: name, $options: "i" } };
      findQuery.push(first, second);
    });

    User.find({ $or: findQuery }).then((users) => {
      res.render("search/index", { users: users });
    });
  },
};

module.exports = SearchController;