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

问题描述 投票:0回答:2

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

  1. 用户的搜索返回每个单词的结果
  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", "[email protected]", "12345");
    cy.signUp("Paul", "Coding", "[email protected]", "12345");
    cy.signUp("Adam", "Woodcock", "[email protected]", "12345");
    cy.signUp("Kathleen", "Woodcock", "[email protected]", "12345");
    cy.signUp("George", "Hett", "[email protected]", "12345");
    cy.signUp("Rob", "Oman", "[email protected]", "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");
  });
});

请您建议我可以进行哪些调整才能使此代码正常运行

javascript express mongoose promise cypress
2个回答
0
投票

您可能会发现这效果更好,尽管我找不到任何由于异步处理而容易失败的地方。

我假设

User.find()
返回一个承诺。

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);
应处理测试端的任何延迟,但如果执行多级搜索可能需要超过 4 秒的时间,您可能需要增加超时。

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

0
投票

我设法通过将上面的内容重构为这个来解决我自己的问题,通过更改 foreach 循环来构建最终查询并将其传递给 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;
© www.soinside.com 2019 - 2024. All rights reserved.