From 83cfba74a83fa530b3b81f7f7ef8b9cec9b4003c Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sat, 4 Apr 2020 14:35:13 -0400 Subject: [PATCH] Use filter documents intead of shelling out to mongo every time --- MongoView.xcodeproj/project.pbxproj | 4 ++ MongoView/Base.lproj/MainMenu.xib | 12 +---- MongoView/ExtendedJSON.swift | 28 +++++++++++ .../DatabaseViewController.swift | 8 +-- .../QueryViewController.swift | 49 +++++++++---------- .../View Controllers/QueryViewController.xib | 2 +- 6 files changed, 59 insertions(+), 44 deletions(-) create mode 100644 MongoView/ExtendedJSON.swift diff --git a/MongoView.xcodeproj/project.pbxproj b/MongoView.xcodeproj/project.pbxproj index df778e5..40e04a7 100644 --- a/MongoView.xcodeproj/project.pbxproj +++ b/MongoView.xcodeproj/project.pbxproj @@ -12,6 +12,7 @@ D60C863F23CA2E2100C9DB8E /* ServerConnectViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D60C863D23CA2E2100C9DB8E /* ServerConnectViewController.swift */; }; D60C864023CA2E2100C9DB8E /* ServerConnectViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = D60C863E23CA2E2100C9DB8E /* ServerConnectViewController.xib */; }; D62408C12438CF550020E09F /* JavaScriptEditorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62408C02438CF550020E09F /* JavaScriptEditorView.swift */; }; + D624090F243903E90020E09F /* ExtendedJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = D624090E243903E90020E09F /* ExtendedJSON.swift */; }; D63CDEBE23C837DC0012D658 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63CDEBD23C837DC0012D658 /* AppDelegate.swift */; }; D63CDEC023C837DD0012D658 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D63CDEBF23C837DD0012D658 /* Assets.xcassets */; }; D63CDEC323C837DD0012D658 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = D63CDEC123C837DD0012D658 /* MainMenu.xib */; }; @@ -86,6 +87,7 @@ D60C863D23CA2E2100C9DB8E /* ServerConnectViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerConnectViewController.swift; sourceTree = ""; }; D60C863E23CA2E2100C9DB8E /* ServerConnectViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ServerConnectViewController.xib; sourceTree = ""; }; D62408C02438CF550020E09F /* JavaScriptEditorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JavaScriptEditorView.swift; sourceTree = ""; }; + D624090E243903E90020E09F /* ExtendedJSON.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtendedJSON.swift; sourceTree = ""; }; D63CDEBA23C837DC0012D658 /* MongoView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MongoView.app; sourceTree = BUILT_PRODUCTS_DIR; }; D63CDEBD23C837DC0012D658 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; D63CDEBF23C837DD0012D658 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; @@ -204,6 +206,7 @@ D63CDF3423C838190012D658 /* MongoController.swift */, D63CDF3323C838190012D658 /* Node.swift */, D6D4665223CB730C00F13B1B /* MongoEvaluator.swift */, + D624090E243903E90020E09F /* ExtendedJSON.swift */, D6A7D0A22435880700B46857 /* Synax Highlighting */, D60C863B23CA2DD600C9DB8E /* Windows */, D60C863C23CA2DDD00C9DB8E /* View Controllers */, @@ -348,6 +351,7 @@ files = ( D63CDEBE23C837DC0012D658 /* AppDelegate.swift in Sources */, D6D4665323CB730C00F13B1B /* MongoEvaluator.swift in Sources */, + D624090F243903E90020E09F /* ExtendedJSON.swift in Sources */, D63CDF3823C8381A0012D658 /* MongoController.swift in Sources */, D60C863923CA2DD100C9DB8E /* ServerConnectWindowController.swift in Sources */, D63CDF3723C8381A0012D658 /* Node.swift in Sources */, diff --git a/MongoView/Base.lproj/MainMenu.xib b/MongoView/Base.lproj/MainMenu.xib index b074263..aa6d81f 100644 --- a/MongoView/Base.lproj/MainMenu.xib +++ b/MongoView/Base.lproj/MainMenu.xib @@ -1,7 +1,7 @@ - + - + @@ -368,14 +368,6 @@ - - -DQ - - - - - diff --git a/MongoView/ExtendedJSON.swift b/MongoView/ExtendedJSON.swift new file mode 100644 index 0000000..7a3092a --- /dev/null +++ b/MongoView/ExtendedJSON.swift @@ -0,0 +1,28 @@ +// +// ExtendedJSON.swift +// MongoView +// +// Created by Shadowfacts on 4/4/20. +// Copyright © 2020 Shadowfacts. All rights reserved. +// + +import Foundation +import JavaScriptCore + +struct ExtendedJSON { + private init() {} + + private static let context: JSContext = { + let context = JSContext()! + let objectId: @convention(block) (String) -> [String: String] = { (id) in + return ["$oid": id] + } + context.setObject(objectId, forKeyedSubscript: "ObjectId" as NSString) + return context + }() + + static func normalize(_ string: String) -> String? { + return context.evaluateScript("JSON.stringify(\(string))")?.toString() + } + +} diff --git a/MongoView/View Controllers/DatabaseViewController.swift b/MongoView/View Controllers/DatabaseViewController.swift index 69d38a1..adf3fff 100644 --- a/MongoView/View Controllers/DatabaseViewController.swift +++ b/MongoView/View Controllers/DatabaseViewController.swift @@ -140,7 +140,7 @@ class DatabaseViewController: NSViewController { } } else if let collection = item as? DatabaseCollection { // only open a new window/tab if our own query has changed from the default, otherwise replace our query controller - if let queryViewController = queryViewController, queryViewController.hasQueryChanged { + if let queryViewController = queryViewController, queryViewController.hasFilterChanged { (NSApplication.shared.delegate as! AppDelegate).newWindow(mongoController: mongoController, collection: collection) } else { self.selectedCollection = collection @@ -149,10 +149,6 @@ class DatabaseViewController: NSViewController { } } - @IBAction func runQuery(_ sender: Any) { - queryViewController?.runQuery() - } - @IBAction func refresh(_ sender: Any) { queryViewController?.refresh() } @@ -160,7 +156,7 @@ class DatabaseViewController: NSViewController { extension DatabaseViewController: NSMenuItemValidation { func validateMenuItem(_ menuItem: NSMenuItem) -> Bool { - if menuItem.action == #selector(runQuery(_:)) || menuItem.action == #selector(refresh(_:)) { + if menuItem.action == #selector(refresh(_:)) { return queryViewController != nil } return true diff --git a/MongoView/View Controllers/QueryViewController.swift b/MongoView/View Controllers/QueryViewController.swift index bd23943..d98b5fe 100644 --- a/MongoView/View Controllers/QueryViewController.swift +++ b/MongoView/View Controllers/QueryViewController.swift @@ -12,19 +12,19 @@ import MongoSwift class QueryViewController: NSViewController { @IBOutlet weak var verticalSplitView: NSSplitView! - @IBOutlet var queryTextView: JavaScriptEditorView! + @IBOutlet var filterTextView: JavaScriptEditorView! @IBOutlet weak var outlineView: NSOutlineView! @IBOutlet weak var documentCountLabel: NSTextField! let mongoController: MongoController let collection: DatabaseCollection - var defaultQuery: String { - "db.getCollection('\(collection.name)').find({}).toArray()" + var defaultFilter: String { + "{}" } - var hasQueryChanged: Bool { - return queryTextView.string != defaultQuery + var hasFilterChanged: Bool { + return filterTextView.string != defaultFilter } var mostRecentQuery: String? = nil @@ -50,9 +50,9 @@ class QueryViewController: NSViewController { verticalSplitView.delegate = self verticalSplitView.setHoldingPriority(.defaultHigh, forSubviewAt: 0) - queryTextView.font = .monospacedSystemFont(ofSize: 13, weight: .regular) - queryTextView.isAutomaticQuoteSubstitutionEnabled = false - queryTextView.string = defaultQuery + filterTextView.font = .monospacedSystemFont(ofSize: 13, weight: .regular) + filterTextView.isAutomaticQuoteSubstitutionEnabled = false + filterTextView.string = defaultFilter outlineView.dataSource = self outlineView.delegate = self @@ -77,32 +77,27 @@ class QueryViewController: NSViewController { } func refresh(reload: Bool = true) { - if let query = mostRecentQuery { - let connStr = "\(mongoController.connectionString)/\(collection.database)" - - rootNodes = MongoEvaluator.eval(command: query, connectingTo: connStr).map { - Node(value: $0) - } - - title = query - documentCountLabel.stringValue = "\(rootNodes.count) result\(rootNodes.count == 1 ? "" : "s")" + let filterText = filterTextView.string.trimmingCharacters(in: .whitespacesAndNewlines) + let filter: Document + if !filterText.isEmpty, + let normalized = ExtendedJSON.normalize(filterText), + let doc = try? Document(fromJSON: normalized) { + filter = doc } else { - let documents = try! mongoController.collection(collection).find().all() - rootNodes = documents.map { Node(document: $0) } - - title = "\(self.collection.database).\(self.collection.name)" - documentCountLabel.stringValue = "\(documents.count) document\(documents.count == 1 ? "" : "s")" + filter = [:] } + + let documents = try! mongoController.collection(collection).find(filter).all() + rootNodes = documents.map { Node(document: $0) } + + title = "\(self.collection.database).\(self.collection.name)" + documentCountLabel.stringValue = "\(documents.count) document\(documents.count == 1 ? "" : "s")" + if reload { outlineView.reloadData() } } - func runQuery() { - mostRecentQuery = queryTextView.string - refresh() - } - func deleteRootNode(_ node: Node) { guard case let .document(doc) = node.value else { return } let alert = NSAlert() diff --git a/MongoView/View Controllers/QueryViewController.xib b/MongoView/View Controllers/QueryViewController.xib index a15357d..d464264 100644 --- a/MongoView/View Controllers/QueryViewController.xib +++ b/MongoView/View Controllers/QueryViewController.xib @@ -8,8 +8,8 @@ + -