GithubHelp home page GithubHelp logo

marinehero / mongokitten Goto Github PK

View Code? Open in Web Editor NEW

This project forked from orlandos-nl/mongokitten

0.0 2.0 0.0 1.42 MB

Native MongoDB driver for Swift, written in Swift

License: MIT License

Swift 99.74% Shell 0.26%

mongokitten's Introduction

MongoKitten

Swift 2.2 Swift 3.0 License Slack Status Carthage compatible

Native MongoDB driver for Swift, written in Swift. This library does not wrap around the mongoc driver. It uses:

  • Strand for fetching server responses without blocking the thread
  • Our own BSON library, which is also 100% native Swift
  • Our own MD5, SHA1 and SCRAM libraries in 100% Swift

Documentation

This can be found here.

We have our own Dash documentation for MongoKitten which can be found in the top-right corner of the Documentation.

Requirements

  • A MongoDB server
  • Some basic knowledge of MongoDB or time to research about MongoDB
  • The swift version described in .swift-version, see swiftenv.

We don't support any other version of swift with the constantly changing syntax. This required swift version changes constantly with newer versions of MongoKitten and it's recommended to pin down the version in SPM.

Note: other versions of swift and MongoDB may or may not work. We do not support them.

Running Unit Tests

The unit tests expect a test database. Run the Tools/testprep.sh script to import it.

Tutorial

Setup

Swift 3.0 (SPM)

Add MongoKitten to your Package.swift:

import PackageDescription

let package = Package(
	name: "MyApp",
	dependencies: [
		.Package(url: "https://github.com/OpenKitten/MongoKitten.git", majorVersion: 1, minor: 1)
	]
)

Swift 2.2 (Carthage)

Add MongoKitten to your Cartfile:

github "OpenKitten/MongoKitten" ~> 1.1

For further instructions, see the Carthage readme.

Note that the tutorial below is written for Swift 3.0. Syntax may be a bit different.

Basic usage

Import the MongoKitten library:

import MongoKitten

Connect to your local MongoDB server using an URI:

let server: Server!

do {
	server = try Server("mongodb://username:password@localhost:27017", automatically: true)

} catch {
    // Unable to connect
	print("MongoDB is not available on the given host and port")
}

Select a database to use for your application:

let database = server["mydatabase"]

And select your collections to use from the database:

let userCollection = database["users"]
let otherCollection = database["otherdata"]

Creating Documents

In MongoKitten we use our own BSON library for working with MongoDB Documents.

You can create a simple user document like this:

var userDocument: Document = [
	"username": "Joannis",
	"password": "myPassword",
	"age": 19,
	"male": true
]

If you want to embed a variable you'll need to use the ~ prefix operator.

let niceBoolean = true

let testDocument: Document = [
    "example": "data",
    "userDocument": ~userDocument,
    "niceBoolean": ~niceBoolean,
    "embeddedDocument": [
        "name": "Henk",
        "male": false,
        "age": 12,
        "pets": ["dog", "dog", "cat", "cat"]
    ]
]

Using Documents

A Document is similar to a Dictionary. A document however has order and thus the position of elements doesn't change unless you tell it to. A Document is therefore an array and a dictionary at the same time. With the minor difference that a Document can only hold BSON's Value. The problem that arises it when you want to use native types from Swift like a String, Int or another Document (sub-document) and elements in there. We fixed this with the use of subscripts and getters.

To get a value from the Document you can subscript it like this:

let username: Value = userDocument["username"]

Documents always return a value. When the value doesn't exist we'll return Value.nothing. If you want to get a specific value from the Document like a String we can return an optional String like this:

let username: String? = userDocument["username"].stringValue

However.. for an age you might want a String without receiving nil in a case like this:

let age: String? = userDocument["age"].stringValue

We made this easier by converting it for you:

let age: String = userDocument["age"].string

However.. if the age would normally be .nothing we'll now return an empty string "" instead. So check for that!

Last but not least we'll also want to assign data using a subscript. Because subscript are prone to being ambiguous we had to use enums for assignment.

This would result in this:

userDocument["bool"] = .boolean(true)
userDocument["int32"] = .int32(10)
userDocument["int64"] = .int64(200)
userDocument["array"] = .array(["one", 2, "three"])
userDocument["binary"] = .binary(subtype: .generic, data: [0x00, 0x01, 0x02, 0x03, 0x04])
userDocument["date"] = .dateTime(NSDate())
userDocument["null"] = .null
userDocument["string"] = .string("hello")
userDocument["objectID"] = .objectId(try! ObjectId("507f1f77bcf86cd799439011"))

Of course variables can still use the ~ operator:

let trueBool = true
userDocument["newBool"] = ~trueBool

Inserting Documents

Using the above document you can insert the data in the collection.

try userCollection.insert(userDocument)

In the collection's insert method you can also insert a group of Documents: [Document]

try otherCollection.insert([testDocument, testDocument, testDocument])

Finding data

To find the Documents in the collection we'll want to use find or findOne on the collection. This returns a "cursor". The find and findOne functions are used on a collection and don't require any parameters. Adding parameters, however, helps finding the data you need. By providing no arguments we're selecing all data in the collection.

let resultUsers = try userCollection.find()

This returns a cursor that you can use to loop over users. MongoKitten's Cursor by default loads 10 Documents at a time from MongoDB which is customizable to a bigger or smaller amount of Documents.

This allows us to provide a smaller delay when looping over data. This also allows the application to remove the cursor halfway through the Documents without downloading Documents that aren't being used.

Looping over the above results is easy:

for userDocument in resultUsers {
	 print(userDocument)
	
    if userDocument["username"].stringValue == "harriebob" {
        print(userDocument)
    }
}

If you do want all Documents in one array you can use Array().

let otherResultUsers = try userCollection.find()
let allUserDocuments = Array(otherResultUsers)

But be careful.. a cursor contains the data only once.

let depletedExample = try userCollection.find()

// Contains data
let allUserDocuments = Array(depletedExample)

// Doesn't contain data
let noUserDocuments = Array(depletedExample)

QueryBuilder

We also have a query builder which can be easily used to create filters when searching for Documents.

let q: Query = "username" == "Joannis" && "age" > 18

let result = try userCollection.findOne(matching: q)

Or simpler:

let newResult = try userCollection.findOne(matching: "username" == "Joannis" && "age" > 18)

This comes in handy when looping over data:

for user in try userCollection.find(matching: "male" == true) {
    print(user["username"].string)
}

Updating data

Updating data is simple too. There is a multiple argument for people who update more than one document at a time. This example only updates the first match:

try userCollection.update(matching: ["username": "Joannis"], to: ["username": "Robbert"])

Deleting data

Deleting is possible using a document and a query

// Delete using a document
try userCollection.remove(matching: ["username": "Robbert"])

GridFS

// Make a GridFS Collection within the database 'mydatabase'
let gridFS = GridFS(in: server["mydatabase"])

// Find all bytes corresponding to this image
let data = NSData(contentsOfFile: "./myimage.jpg")!

// Store the file in GridFS with maximum 10000 bytes per chunk (255000 is the recommended default) and doesn't need to be set
// Store the ObjectID corresponding to the file in a constant variable
let objectID = try! gridFS.store(data: data, named "myimage.jpg", withType: "image/jpeg", inChunksOf: 10000)

// Retreive the file from GridFS
let file = try! gridFS.findOne(byID: objectID)

// Get the bytes we need
let myImageData: [Byte] = file!.read(from: 1024, to: 1234)

GridFS example usage

Imagine running a video streaming site. One of your users uploads a video. This will be stored in GridFS within 255000-byte chunks.

Now one user starts watching the video. You'll load the video chunk-by-chunk without keeping all of the video's buffer in memory.

The user quits the video about 40% through the video. Let's say chunk 58 of 144 of your video. Now you'll want to start continueing the video where it left off without receving all the unneccesary chunks.

License

MongoKitten is licensed under the MIT license.

mongokitten's People

Contributors

joannis avatar obbut avatar loganwright avatar

Watchers

James Pereira avatar James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.