Building an api with several arrays which can be updated - node.js

I'm new to noSQL and i'm trying to figure out how to create the best possible model structure. What i need to do is every hour to retrieve leagues and matches from an api and add it to my database. Every hour the score might change and new matches might be added to each league and therefor this should be possible in the model. i've read the documentation and created following, however i'm not sure it is possible to update each and add new matches to leagues. What is the ideal modelling for such?
Tournament model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var League = require('./league');
var TournamentSchema = new Schema({
slug: String,
tournaments: [League]
});
module.exports = mongoose.model('Tournament', TournamentSchema);
League
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Match = require('./match');
var leagueSchema = new Schema({
leaguetId: Number,
name: String,
matches: [Match]
});
module.exports = mongoose.model('League', leagueSchema);
Match
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var matchSchema = new Schema({
homeTeam: String,
awayTeam: String,
homeScore: Number,
awayScore: Number,
start: Date
});
module.exports = mongoose.model('Match', matchSchema);
Post request so far
router.post('/tournaments', function(req, res, next) {
var tournament = new Tournament(); // create a new instance of the Bear model
tournament.name = req.body.slug; // set the bears name (comes from the request)
// save the bear and check for errors
tournament.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Tournament created!' });
});
});

If you're adding new matches to leagues and updating matches on a timed interval, why nest them within each other? Lets say you have a match with id 5 whose score changed. In order to find it to update it you'd have to first go through each league, and then iterate through each match in each league until you find the match with id 5. Unless I'm mistaken and there's some easier way to do it, this seems very inefficient.
Why not have two collections? A league collection and a match collection. There will be a 1 (league) : many (match) relationship. When you need to update a match's score, who cares what league it's in? Search the match collection for id 5, and update it.
What would a new match look like? Lets say a league with id 7 had a new match. Add a match to the match collection that has a league id of 7.
If you're really opposed to moving away from one collection.. at least store your matches in an object instead of an array, that way you can find matches with an O(1) lookup time by using it's match name. Instead of O(n) or O(n^2) lookup time like you currently have.

Related

How to get join result using mongoose populate, match (2 collections)

User Schema
var UsersSchema = new Schema({
username:String,
city:String
},{collection:'User'});
//sample data {'username':'7700010000',city:'mumbai'}
College Schema
var College = new Schema({
college:String,
user_sess:[type:String,ref:"User"]},{collection:'College'});
//sample data {'college':'adarsh college','user_sess':'Sess$7700010000'}
I am trying to get result from college collection based on user_sess. but problem is user_sess has value with prefix value 'Sess$'
so user_sess = prefix + username from collection User
var prefix = 'Sess$';
College
.find({ "user_sess": prefix + req.body.user_id})
.populate({'user_sess'})
.exec(function (err, users) {
console.log();
if (err)
res.send(err);
res.json(users);
});
If there is a match for user_sess then result should look like
{'college':'adarsh college','username':'7700010000','city':'mumbai'}
I already solved it by adding reference keys in my respective collection because I i tried regex but it added extra latency in my responses. We are using parse server framework but we want to get rid of it but since parse saves data differently I was not able to do joins using mongoose schema.
Thank you.

Check stored value using mongoose

I’m looking for the fastest way to get all objectIDs of a collection with a privacy value 'public'.
In this image, privacy's value is 'public', so node should give me the '_id' of this object (in this example '57bc4b9f466fab7c099a3f94').
My attempt:
var mongoose = require('mongoose');
mongoose.connect('localhost:27017/databasename');
var Schema = mongoose.Schema;
var collectionsNameSchema = new Schema({
updated: {type: Date },
privacy: { type: Object }
}, {collection: 'spots'});
var collectionsNameData = mongoose.model('collectionsNameData', collectionsNameSchema);
...
collectionsNameData.find({privacy: 'public'})
From what i see you have a problem in query to mongoDB.
Try like this.
collectionsNameData.find({'privacy.value': 'public'});
This should return desired result.
You also may want to use projection as second parameter in find to return only fields that you want. Keep in mind that _id returned by default.
Hope this helps.

Is it possible to search multiple Mongoose models at once?

I have four Mongoose models, SoleTrader, Partnership, Company and Trust. They’re different enough that I can’t merge them all into one schema, yet similar enough that I regularly need to query or make changes to all 4 types at once and rarely care which sort they are.
Is there a way of doing this – possibly by putting all four types in a single collection – without making four database calls each time?
Since you're using mongoose-schema-extend, it seem like you could create a simple 'base' schema and extend your other schema's off that. If you want to search across all of them, use the base model.
For instance:
// base schema
var PersonSchema = new Schema({
name : String
}, {
collection : 'users', // everything will get saved in the same collection
discriminatorKey : '_type'
});
// two schema's that extend off it
var EmployeeSchema = PersonSchema.extend({ department : String });
var EmployerSchema = PersonSchema.extend({});
// materialize all three into models
var Person = mongoose.model('Person', PersonSchema);
var Employee = mongoose.model('Employee', EmployeeSchema);
var Employer = mongoose.model('Employer', EmployerSchema);
...
// create some people
new Employee({
name : 'Homer Simpson',
department : 'Safety'
}).save(...);
new Employer({
name : 'Charles Montgomery Burns',
}).save(...);
...
// search across employers and employees
Person.find({ ... }, function(err, people) {
...
});
However, I have to say that the advertised behaviour of find() returning the correct model instance according to the discriminator key doesn't work for me.

Getting all documents from MongoDB instead of all Models

I'm calling MongoDB from my Node app using Mongoose like this:
var query = itemModel.find();
query.exec(function (err, items) {
console.log(err);
socket.emit("items", items);
});
I have 3 models defined like this:
var Schema = mongoose.Schema
, ObjectId = Schema.ObjectId;
var playerModel = require('./models/player.js').make(Schema, mongoose);
var characterModel = require('./models/character.js').make(Schema, mongoose, ObjectId);
var itemModel = require('./models/item.js').make(Schema, mongoose);
my models look like this:
function make(Schema, mongoose) {
itemSchema = new Schema({
name: String
, bonus: [{
type: String
, value: Number
}]
, price: Number
, slot: String
});
return mongoose.model('Character', characterSchema);
}
exports.make = make;
For some reason I'm getting all documents, regardless of them being items, characters or players. Since I'm calling find() on itemModel I was expecting only Items, what am I doing wrong?
The model that you have shown appears to be the item model, but you are creating the model with the 'Character' name. This means that you told Mongoose about the scheme for an item and that it is stored in the 'character' collection. Assuming you've done the same for each other model (Character/Player), you've been Mongoose that everything is in the same collection.
Then you query that collection and you seem surprised that everything is stored in the same collection. It strikes me as if you have little experience with Mongoose/MongoDB, so I will suggest you download and learn to love MongoVUE. This application is a good GUI to see what is going on under the hood of the MongoDB database. While developing, you also might want to enable debugging so you can see what queries mongoose is launching to the server (mongoose.set('debug', true)).

finding objectIds between two given values in mongodb and nodejs

I am creaing schemas similar to newsposts with an option for users to like and dislike them.
Here are the schemas for same
Client= new mongoose.Schema({
ip:String
})
Rates = new mongoose.Schema({
client:ObjectId,
newsid:ObjectId,
rate:Number
})
News = new mongoose.Schema({
title: String,
body: String,
likes:{type:Number,default:0},
dislikes:{type:Number,default:0},
created:Date,
// tag:String,
client:ObjectId,
tag:String,
ff:{type:Number,default:20}
});
var newsm=mongoose.model('News', News);
var clientm=mongoose.model('Client', Client);
var ratesm=mongoose.model('Rates', Rates);
In order to retreive the ratingsgiven by a particular user having given a set of newsposts, I tried,
newsm.find({tag:tag[req.params.tag_id]},[],{ sort:{created:-1},limit: buffer+1 },function(err,news){
ratesm.find({
client:client._id,
newsid:{$lte:news[0]._id,$gte:news.slice(-1)[0]._id}
},
function(err,ratings){
})
})
This query returns empty list no matter what. I doubt whether $gte and $lte be used to compare objectIds. Am I right? How can I which posts a user has liked/disliked in a given set of newsposts?
Yes, ObjectIds can be queried with range queries like $gt/$lt etc. Can you post the exact values being used for news[0]._id and news.slice(-1)[0]._id that are giving you the empty result?
However, i'm not sure that $gt/$lt is what you want here. It seems like what you need to do is extract the _ids of the news items, and then use that in a $in filter in your query on ratesm.

Resources