Cocoa, Objective C MongoDB App using ObjCMongoDB.framework
Written by: Debasis Das (23-Jan-2015)
In this article we will create a simple Cocoa, Objective C App that connects to MongoDB Database through the ObjCMongoDB.framework
We will implement the following functionality in this project
- Create an Employee Collection in a Database in MongoDB
- Implement Find Functionality
- Implement Add New Employee
- Implement Modify Existing Employee & Save
- Delete Employee Record
The signature of each employee record in the MongoDB Collection will be as follows
/* > db.employees.findOne() { "_id" : ObjectId("54347187dbbd79a1510148b3"), "employee_id" : "1000", "first_name" : "John", "last_name" : "Doe", "email" : "JohnDoe@knowstack.com", "phone_number" : "408-000-0000", "salary" : 713077, "year_exp" : 30, "designation" : "Senior Director", "department" : "Finance" } */
// // CocoaMongoWindowController.m // KSCocoaMongo // // Created by Debasis Das on 1/22/15. // Copyright (c) 2015 Knowstack. All rights reserved. // #import "CocoaMongoWindowController.h" extern NSString *const HOST_WITH_PORT; extern NSString *const COLLECTION_NAME; @class EmployeeWindowController; @interface CocoaMongoWindowController () @property (nonatomic, assign) IBOutlet NSTableView *employeeTableView; @property (nonatomic, assign) IBOutlet NSPopUpButton *designationPopupButton; @property (nonatomic, assign) IBOutlet NSPopUpButton *salaryQueryPopupButton; @property (nonatomic, assign) IBOutlet NSTextField *salaryTextField; @end @implementation CocoaMongoWindowController //Following is the structure of data that will be displayed in this screen /* > db.employees.findOne() { "_id" : ObjectId("54347187dbbd79a1510148b3"), "employee_id" : "1000", "first_name" : "John", "last_name" : "Doe", "email" : "JohnDoe@knowstack.com", "phone_number" : "408-000-0000", "salary" : 713077, "year_exp" : 30, "designation" : "Senior Director", "department" : "Finance" } */ NSString *const HOST_WITH_PORT = @"127.0.0.1"; NSString *const COLLECTION_NAME = @"knowstack.employees"; - (void)windowDidLoad { [super windowDidLoad]; // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. } -(NSString *)windowNibName { return @"CocoaMongoWindow"; } -(IBAction)find:(id)sender { NSError *error = nil; MongoConnection *dbConn = [MongoConnection connectionForServer:HOST_WITH_PORT error:&error]; MongoDBCollection *collection = [dbConn collectionWithName:COLLECTION_NAME]; MongoKeyedPredicate *predicate = [MongoKeyedPredicate predicate]; if ([self.salaryTextField intValue] !=0) { if ([[self.salaryQueryPopupButton titleOfSelectedItem] isEqualToString:@">"]) { [predicate keyPath:@"salary" isGreaterThan:@([self.salaryTextField intValue])]; } else if ([[self.salaryQueryPopupButton titleOfSelectedItem] isEqualToString:@"<"]) { [predicate keyPath:@"salary" isLessThan:@([self.salaryTextField intValue])]; } else if ([[self.salaryQueryPopupButton titleOfSelectedItem] isEqualToString:@"="]) { [predicate keyPath:@"salary" matches:@([self.salaryTextField intValue])]; } } NSArray *bSonArray = [collection findWithPredicate:predicate error:&error]; NSMutableArray *mArray = [[NSMutableArray alloc] init]; for (BSONDocument *doc in bSonArray) { [mArray addObject:[BSONDecoder decodeDictionaryWithDocument:doc]]; } [self setDataArray:mArray]; [mArray release]; [self.employeeTableView reloadData]; } -(IBAction)modify:(id)sender { NSDictionary *employeeRecord = [self.dataArray objectAtIndex:[self.employeeTableView selectedRow]]; [EmployeeWindowController initWithData:employeeRecord]; } -(IBAction)delete:(id)sender { NSError *error = nil; MongoConnection *dbConn = [MongoConnection connectionForServer:HOST_WITH_PORT error:&error]; MongoDBCollection *collection = [dbConn collectionWithName:COLLECTION_NAME]; MongoKeyedPredicate *predicate = [MongoKeyedPredicate predicate]; [predicate keyPath:@"_id" matches:[[self.dataArray objectAtIndex:[self.employeeTableView selectedRow]] objectForKey:@"_id"]]; [collection removeWithPredicate:predicate writeConcern:nil error:&error]; [self find:self]; if (error == NULL) { NSAlert *alert = [[NSAlert alloc] init]; [alert setMessageText:@"Delete Confirmation"]; [alert setInformativeText:@"The Employee has been deleted"]; [alert runModal]; } } -(IBAction)addEmployee:(id)sender { EmployeeWindowController *ewc = [[EmployeeWindowController alloc] init]; [ewc showWindow:self]; } - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(NSInteger)rowIndex { NSString *aString; aString = [[self.dataArray objectAtIndex:rowIndex] objectForKey:[aTableColumn identifier]]; return aString; } - (void)tableView:(NSTableView *)tableView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row { [[self.dataArray objectAtIndex:row] setObject:object forKey:[tableColumn identifier]]; } - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { long recordCount = [self.dataArray count]; return recordCount; } @end
@interface EmployeeWindowController : NSWindowController @property (assign) IBOutlet NSTextField *employeeIdTextField; @property (assign) IBOutlet NSTextField *firstNameTextField; @property (assign) IBOutlet NSTextField *lastNameTextField; @property (assign) IBOutlet NSTextField *emailTextField; @property (assign) IBOutlet NSTextField *phoneNumTextField; @property (assign) IBOutlet NSTextField *salaryTextField; @property (assign) IBOutlet NSTextField *yearExpTextField; @property (assign) IBOutlet NSTextField *designationTextField; @property (assign) IBOutlet NSTextField *departmentTextField; @property (nonatomic, retain) NSDictionary *employeeDictionary; @property (nonatomic, retain) NSString *recordId; @end @implementation EmployeeWindowController @synthesize employeeIdTextField; -(NSString *)windowNibName { return @"EmployeeWindow"; } +(void)initWithData:(NSDictionary *)employeeRecord { EmployeeWindowController *obj = [[EmployeeWindowController alloc] init]; [obj setEmployeeDictionary:employeeRecord]; [obj showWindow:self]; } -(void)awakeFromNib { NSDictionary *emp = self.employeeDictionary; if (emp) { //Record Exists. This is a modify request [self.window setTitle:@"Modify Employee"]; [self setRecordId:[emp objectForKey:@"_id"]]; [self.employeeIdTextField setStringValue:[emp objectForKey:@"employee_id"]]; [self.employeeIdTextField setEnabled:NO]; [self.firstNameTextField setStringValue:[emp objectForKey:@"first_name"]]; [self.lastNameTextField setStringValue:[emp objectForKey:@"last_name"]]; [self.emailTextField setStringValue:[emp objectForKey:@"email"]]; [self.phoneNumTextField setStringValue:[emp objectForKey:@"phone_number"]]; [self.salaryTextField setStringValue:[emp objectForKey:@"salary"]]; [self.yearExpTextField setStringValue:[emp objectForKey:@"year_exp"]]; [self.designationTextField setStringValue:[emp objectForKey:@"designation"]]; [self.departmentTextField setStringValue:[emp objectForKey:@"department"]]; } else { //This is a new employee creation [self.window setTitle:@"Add New Employee"]; NSLog(@"Do Nothing"); } } -(IBAction)saveEmployee:(id)sender { NSError *error = nil; MongoConnection *dbConn = [MongoConnection connectionForServer:HOST_WITH_PORT error:&error]; MongoDBCollection *collection = [dbConn collectionWithName:COLLECTION_NAME]; NSString *uniqueIdString = nil; if (self.recordId) { //Modify Request uniqueIdString = self.recordId; } else { NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"MMddyyyyhhmmss"]; uniqueIdString = [dateFormatter stringFromDate:[NSDate date]]; } NSDictionary *employeeRecord = [NSDictionary dictionaryWithObjectsAndKeys: uniqueIdString,@"_id", [self.employeeIdTextField stringValue],@"employee_id", [self.firstNameTextField stringValue],@"first_name", [self.lastNameTextField stringValue],@"last_name", [self.emailTextField stringValue],@"email", [self.phoneNumTextField stringValue],@"phone_number", [self.salaryTextField stringValue],@"salary", [self.yearExpTextField stringValue],@"year_exp", [self.designationTextField stringValue],@"designation", [self.departmentTextField stringValue],@"department", nil]; if (self.recordId) { //Update Request MongoKeyedPredicate *predicate = [MongoKeyedPredicate predicate]; [predicate keyPath:@"_id" matches:self.recordId]; MongoUpdateRequest *updateRequest = [MongoUpdateRequest updateRequestWithPredicate:predicate firstMatchOnly:NO]; [updateRequest keyPath:@"first_name" setValue:[self.firstNameTextField stringValue]]; [updateRequest keyPath:@"last_name" setValue:[self.lastNameTextField stringValue]]; [updateRequest keyPath:@"email" setValue:[self.emailTextField stringValue]]; [updateRequest keyPath:@"phone_number" setValue:[self.phoneNumTextField stringValue]]; [updateRequest keyPath:@"salary" setValue:[self.salaryTextField stringValue]]; [updateRequest keyPath:@"year_exp" setValue:[self.yearExpTextField stringValue]]; [updateRequest keyPath:@"designation" setValue:[self.designationTextField stringValue]]; [updateRequest keyPath:@"department" setValue:[self.departmentTextField stringValue]]; [collection updateWithRequest:updateRequest error:&error]; if (error == NULL) { NSAlert *alert = [[NSAlert alloc] init]; [alert setMessageText:@"Successfully Updated"]; [alert setInformativeText:@"The Employee changes has been successfully updated"]; [alert runModal]; } } else { //Insert Request [collection insertDictionary:employeeRecord writeConcern:nil error:&error]; if (error == NULL) { NSAlert *alert = [[NSAlert alloc] init]; [alert setMessageText:@"New Employee Added"]; [alert setInformativeText:@"The Employee has been added"]; [alert runModal]; } } } @end
You can download the source code from here
For further read on MongoDB
For further read on ObjCMongoDB
Leave a Reply