forked from elasticnotorious/curates
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mongo.js
208 lines (191 loc) · 5.37 KB
/
mongo.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
// Establish connection with the server
var connectionString = process.env.CURATES_DB_URI || process.env.WERCKER_MONGODB_URL;
var mongoose = require('mongoose');
mongoose.connect(connectionString);
var db = mongoose.connection;
// Attach useful listeners to the database
db.on('error', function(error) {
console.error('Mongoose encountered an error:', error);
});
db.once('open', function() {
console.log('Mongoose successfully opened connection with the database');
});
// Set up Schema
var collectionSchema = new mongoose.Schema({
title: {
type: String,
required: true
},
url: {
type: String,
required: true
},
user: {
type: {
provider: String,
id: String,
fullName: String,
givenName: String
},
required: true
},
description: {
type: String,
required: true
},
links: [{
url: String,
title: String,
description: String,
stars: {
type: Number,
default: 0
}
}],
userStars: {
type: [],
default: []
},
createdAt: {
type: Date,
default: Date.now
},
updatedAt: {
type: Date,
default: Date.now
},
stars: {
type: Number,
default: 0
}
});
var Collection = mongoose.model('Collection', collectionSchema);
// Used to retrieve only these fields in some queries
var metaFields = '_id title url user description stars';
// mongo will be exported. This is the interface for using the database.
var mongo = {};
// An function for mapping a collection title to a url
mongo.mapTitleToUrl = function(title) {
// These are the allowed charachters, all others are removed
return title.replace(/[^A-Za-z0-9\-]/g, '').toLowerCase();
};
// Attempts to create a new collection
// If there is already a collection in the db with the same url,
// returns null, else
// Returns a promise
mongo.create = function(coll) {
// Sets the url if it not already set
// Should this even be an option? maybe it should require the
// url to be set here?
if (!coll.url) {
coll.url = mongo.mapTitleToUrl(coll.title);
}
// Check that url is unique
return mongo.findByUrl(coll.url).then(function(collection) {
if (collection) return null;
return Collection.create(coll);
});
};
// Attempts to find the collection with the given id
// Returns a promise
mongo.findById = function(id) {
return Collection.findById(id).exec();
};
// Attempts to find ONE collection by the given title
// Returns a promise
mongo.findByTitle = function(title) {
return Collection.findOne({
title: title
}).exec();
};
// Attempts to find ONE collection with the given url
// There should never be multiple collections with the same url
// Returns a promise
mongo.findByUrl = function(url) {
return Collection.findOne({
url: url
}).exec();
};
// Saves changes of the given collection to the database
// Note: url, title, and user should not be changed, TODO: validate for this?
// Returns a promise that resolves to the new collection
mongo.update = function(collection) {
// default find by id (fastest)
if (collection._id) {
var id = collection._id;
delete collection._id;
collection.updatedAt = Date.now();
return Collection.findByIdAndUpdate(id, collection).exec();
} else {
// find by title (mostly to make testing easier)
collection.updatedAt = Date.now();
return Collection.findOneAndUpdate({
title: collection.title
},
collection
).exec();
}
};
// Adds a link to the given document
// Expects data to have _id and links properties:
// {
// _id: the collection to add to
// links: [
// { url: String, title: String, description: String }
// ]
// }
// Can add an arbitrary number of links
mongo.addLink = function(data) {
return Collection.findByIdAndUpdate(data._id, {
$push: {
links: {
$each: data.links
}
}
}).exec();
};
// If the provided user has not already starred this
// collection, adds a star to the collection
//
// Expects data to have _id and user properties:
// {
// _id: the collection to add to
// user: [
// {
// provider: String,
// id: String,
// fullName: String,
// givenName: String
// }
// ]
// }
// Returns a promise that resolves to the updated collections
mongo.addStar = function(data) {
// Stringify the user
// This should be unique to every user
var userString = data.user.provider + data.user.id;
return Collection.findByIdAndUpdate(data._id, {
$addToSet: { userStars: userString }
}).exec()
.then(function(collection) {
var update = {};
update._id = collection._id;
update.stars = collection.userStars.length;
return mongo.update(update);
});
};
// Returns a promise that resolves to an array of objects, each
// containing the meta data of all the collections in the database
mongo.getAllCollections = function() {
return Collection.find({}, metaFields).exec();
};
// Returns a promise that resolves to an array of objects, each
// containing the meta data of all the collections created by the
// given user
mongo.getUserCollections = function(user) {
return Collection.find({
'user.provider': user.provider,
'user.id': user.id
}, metaFields).exec();
};
module.exports = mongo;