如何在mongodb中按值数组排序

时间:2019-03-11 11:00:21

标签: mongodb mongodb-query

我有一个Mongodb集合,其中包含具有一定尺寸的产品,我想按一定顺序对其进行排序。

在SQL中,您可以进行import Foundation protocol ExampleService { typealias PersonCompletion = (PagedResult<Person>) -> Void func persons(page: Int, resultsPerPage: Int, completion: @escaping PersonCompletion) } class ExampleWebService: ExampleService { func persons(page: Int, resultsPerPage: Int, completion: @escaping (PagedResult<Person>) -> Void) { let url = URL(string: "https://example.com/api/?action=persons_detailed&limit=\(resultsPerPage)")! let task = session.dataTask(with: url) { (data, response, error) in guard let data = data else { return } do { try validate(response) let persons: [Person] = try parse(data) let personPage = PagedResult(pageNumber: page, results: persons) completion(personPage) print(data) } catch { print("Error: \(error)") } } task.resume() } } size import UIKit class PersonListViewController: UIViewController { @IBOutlet weak var collectionView: UICollectionView! var personPages: [PagedResult<Person>] = [] { didSet { DispatchQueue.main.async { self.collectionView.reloadData() } } } override func viewDidLoad() { super.viewDidLoad() loadPersons() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) guard let selectedIndexPath = collectionView.indexPathsForSelectedItems?.first else { return } collectionView.deselectItem(at: selectedIndexPath, animated: animated) } var service = ExampleWebService() private func loadPersons(page: Int = 0, resultsPerPage: Int = 10) { service.persons(page: page, resultsPerPage: resultsPerPage) { (personPage) in guard !self.loadedPersonPageNumbers.contains(page) else { return } self.personPages.append(personPage) self.updateLastIndexPath(personPage) } } private(set) var lastIndexPath: IndexPath? private func updateLastIndexPath(_ personPage: PagedResult<Person>) { if personPage.results.isEmpty { lastIndexPath = nil } else { lastIndexPath = calculateLastIndexPath() } } private func calculateLastIndexPath() -> IndexPath? { guard let lastPage = personPages.last else { return nil } let section = lastPage.pageNumber let row = lastPage.results.count - 1 return IndexPath(row: row, section: section) } fileprivate var loadedPersonPageNumbers: [Int] { return personPages.map { $0.pageNumber } } func person(at indexPath: IndexPath) -> Person? { guard indexPath.section < personPages.count else { return nil } guard indexPath.row < personPages[indexPath.section].results.count else { return nil } let page = personPages[indexPath.section] return page.results[indexPath.row] } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { guard let personViewController = segue.destination as? PersonViewController, let selectedIndexPath = collectionView.indexPathsForSelectedItems?.first else { return } personViewController.person = person(at: selectedIndexPath) } @IBAction func exitToPersonsView(segue: UIStoryboardSegue) { } } extension PersonListViewController: UICollectionViewDelegate { fileprivate var nextPageIndex: Int { guard let lastPage = personPages.last else { return 0 } return lastPage.pageNumber.advanced(by: 1) } func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { if indexPath == lastIndexPath { loadPersons(page: nextPageIndex) } } } 的操作,但是我完全不知道如何使用mongodb实现这种操作。

1 个答案:

答案 0 :(得分:2)

不幸的是sort(for queries)/orderBy(for aggregations)遵循以下语法:

<field1>: <sort order>;

因此,您不能复制与SQL中相同的行为。 您的解决方案可能是在过滤器中传递orderBy / sort,然后再次查询这些结果。

另一种解决方案是使用聚合,但是您必须指定最终结果中要包含产品中的哪些字段:

db.products.aggregate( [ { $group : { _id : "$size", products: { $push: "$name" } } } ] )

响应如下所示:

  

{“ _id”:“ L”,“产品”:[]} {“ _id”:“ M”,“产品”:[   “ a”,“ b”]}

另一个聚合示例,该示例首先过滤产品,然后将它们分组:

 db.products.aggregate([   
   { $match: { size: { $in: ["M", "L"] } } },   
   { $group: { _id: "$size", products: { $push: {name: "$name", size:"$size"} } } }
 ]);

// { "_id" : "M", "products" : [ { "name" : "a2", "size" : "M" } ] }
// { "_id" : "L", "products" : [ { "name" : "a1", "size" : "L" }, { "name" : "a3", "size" : "L" } ] }