如何在应用中搜索用户? (最具成本效益的方式)在 Firebase

Posted

技术标签:

【中文标题】如何在应用中搜索用户? (最具成本效益的方式)在 Firebase【英文标题】:How to search for users in app? (the most cost efficient way) in Firebase 【发布时间】:2018-10-23 07:45:48 【问题描述】:

我使用 firebase 制作了一个小型 MVP 测试应用。我还制作了一个用于搜索用户的 ViewController。但是现在,一旦单击 searchcontroller,我就必须加载 firebase 项目中的每个用户。这不是非常可扩展的。 (搜索控制器显示用户的用户名和个人资料照片。

我有它,所以用户必须在 searchcontroller 开始在 tableview 中显示内容之前输入至少两个单词。所以也许一个解决方案是只在点击时加载用户名,然后只在显示当前用户时加载个人资料图片?如果是这样,我该如何实现?

class FollowUsersTableViewController: UIViewController

@IBOutlet var tableView: UITableView!

private var viewIsHiddenObserver: NSKeyValueObservation?
let searchController = UISearchController(searchResultsController: nil)
var usersArray = [UserModel]()
var filteredUsers = [UserModel]()
var loggedInUser: User?
//
var databaseRef = Database.database().reference()
//usikker på den koden over

override func viewDidLoad() 
    super.viewDidLoad()
    //large title
    self.title = "Discover"
    if #available(ios 11.0, *) 
        self.navigationController?.navigationBar.prefersLargeTitles = true
     else 
        // Fallback on earlier versions
    

    self.tableView?.delegate = self
    self.tableView?.dataSource = self
    searchController.searchResultsUpdater = self
    searchController.dimsBackgroundDuringPresentation = false
    self.searchController.delegate = self;

    definesPresentationContext = true
    tableView.tableHeaderView = searchController.searchBar

    self.loadProfileData()


func loadProfileData() 
    databaseRef.child("profile").queryOrdered(byChild: "username").observe(.childAdded, with:  (snapshot) in
        print(snapshot)
        let userObj =  Mapper<UserModel>().map(JSONObject: snapshot.value!)
        userObj?.uid = snapshot.key

        guard snapshot.key != self.loggedInUser?.uid else  return 

        self.usersArray.append(userObj!)
    )


override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
    let dest = segue.destination as! UserProfileViewController
    let obj = sender as! UserModel
    let dict = ["uid": obj.uid!, "username": obj.username!, "photoURL": obj.photoURL, "bio": obj.bio]
    dest.selectedUser = dict as [String : Any]


  

   // MARK: - tableview methods
   extension FollowUsersTableViewController: UITableViewDataSource, 
  UITableViewDelegate 

func tableView(_ tableView: UITableView, numberOfRowsInSection 
 section: Int) -> Int 
    return searchController.searchBar.text!.count >= 2 ? 
 filteredUsers.count : 0
  

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! FollowTableViewCell

    let user = filteredUsers[indexPath.row]

    cell.title?.text = user.username
    if let url = URL(string: user.photoURL ?? "") 
        cell.userImage?.sd_setImage(with: url, placeholderImage: 
     #imageLiteral(resourceName: "user_male"), options: 
  .progressiveDownload, completed: nil)
        cell.userImage.sd_setIndicatorStyle(.gray)
        cell.userImage.sd_showActivityIndicatorView()
    

    return cell


 func tableView(_ tableView: UITableView, heightForRowAt indexPath: 
   IndexPath) -> CGFloat 
    return 50


func tableView(_ tableView: UITableView, didSelectRowAt indexPath: 
 IndexPath) 
    self.performSegue(withIdentifier: "user", sender: self.filteredUsers[indexPath.row])


 

 // MARK: - search methods
 extension FollowUsersTableViewController:UISearchResultsUpdating, 
   UISearchControllerDelegate 

func updateSearchResults(for searchController: UISearchController) 
    searchController.searchResultsController?.view.isHidden = false
    filterContent(searchText: self.searchController.searchBar.text!)
    self.tableView.reloadData()


func filterContent(searchText:String)
    if searchText.count >= 2
        self.filteredUsers = self.usersArray.filter user in
            return(user.username!.lowercased().contains(searchText.lowercased()))
        
    
   
  

【问题讨论】:

【参考方案1】:

你可以使用queryStartingAtValue:

func searchQueryUsers(text: String, completion: @escaping (_ userNames: [String]) -> Void) 

    var userNames: [String] = []

    databaseRef.child("profile").queryOrdered(byChild: "username").queryStarting(atValue: text).observeSingleEvent(of: .value, with:  snapshot in

        for item in snapshot.children 

            guard let item = item as? DataSnapshot else 
                break
            

            //"name" is a key for name in FirebaseDatabese model
            if let dict = item.value as? [String: Any], let name = dict["name"] as? String 
                userNames.append(name)
            
        

        completion(userNames)
    )

【讨论】:

谢谢老兄,但是“queryStarting(atValue: text)”你说的文本是什么意思?我还应该用你的 func searchQueryUsers 替换我的 func loadProfileData(),还是只添加 queryStarting atValue ? "text" 这是您的用户名(或名称的一部分)。例如,名称 =“马特”-> 文本 =“马”。此外,您不需要下载所有用户数据,使用 queryStartingAtValue 代替 loadProfileData() 但是这不加载个人资料图片?要不然是啥?你介意改变你的代码,以便我可以更清楚地看到它如何与我的变量和 jsonObject 用户模型映射器一起工作吗? (对不起,我是 firebase 新手,之前只使用过 aws) 我也应该使用 searchController.searchBar.text 作为文本吗?

以上是关于如何在应用中搜索用户? (最具成本效益的方式)在 Firebase的主要内容,如果未能解决你的问题,请参考以下文章

如何以具有成本效益的方式自动扩展 AWS 和 GCP 中的突然请求峰值?

MongoDB到DynamoDB

如何通过管理提升企业采购效益?

UWB技术的工作原理

DbVisualizer:开发人员DBA和分析师的通用数据库工具!

如何深入了解 Facebook 页面关注者 + 具有成本效益的自动化数字营销软件解决方案