Skip to content

Commit

Permalink
Improve reduce with speed and filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
j1348 authored and jfroffice committed Dec 29, 2018
1 parent 7403d33 commit 7c2e7e4
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 61 deletions.
13 changes: 1 addition & 12 deletions src/graphql/resolvers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,7 @@ import { getRepo, getReposFast } from './repo';

export default {
Query: {
getRepos: getReposFast,
getRepos: (_, params) => getReposFast(params),
getRepo: (_, { id }) => getRepo(id),
},
Repo: {
Ticks: ({ ticks }) => {
return ticks.map(({ stars, forks, date }) => {
return {
stars,
forks,
date,
};
});
},
},
};
53 changes: 43 additions & 10 deletions src/graphql/resolvers/repo/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,58 @@ export function getManyRepos(ids) {
);
}

export function getRepoRefs() {
return Reporef.find({});
}

export function getRepo(id) {
return Repo.find({ _id: id }).map(
({ _id: id, name, author, language, href, description }) => {
({ _id: id, name, author, language, href, description, ticks }) => {
return {
id,
name,
author,
language,
href,
description,
ticks,
};
},
);
}

export function getReposFast() {
return getRepoRefs().then(data => {
export function getRepoRefs(filter) {
let query = {};
if (filter) {
if (filter.from || filter.to) {
query = { 'value.dates': {} };
if (filter.from) {
query['value.dates']['$gte'] = filter.from;
}
if (filter.to) {
query['value.dates']['$lte'] = filter.to;
}
} else if (filter.at) {
query = { 'value.dates': filter.at };
} else if (filter.name) {
query = { 'value.name': filter.name };
} else {
query = { 'value.date': new Date().toISOString().slice(0, 10) };
}
}
return Reporef.find(query);
}

function sortByDate(a, b) {
if (a.date < b.date) {
return 1;
}

if (a.date > b.date) {
return -1;
}

return 0;
}

export function getReposFast(params) {
return getRepoRefs(params).then(data => {
const ids = data.map(d => d._id);
const metaInfo = data.reduce((result, { _doc: { value }, _id }) => {
result[_id] = value;
Expand All @@ -37,20 +68,22 @@ export function getReposFast() {
return getManyRepos(ids).then(repos => {
const newRepos = repos.map(
({ _id: id, name, description, author, language, href }) => {
const { date, stars, starsByDay } = metaInfo[id];
const { stars, date, dates, speed } = metaInfo[id];
return {
id,
name,
description,
author,
language,
href,
date,
stars,
starsByDay,
date,
dates,
speed,
};
},
);
newRepos.sort(sortByDate);
return newRepos;
});
});
Expand Down
88 changes: 53 additions & 35 deletions src/graphql/resolvers/repo/model.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import moment from 'moment';
import mongoose from 'mongoose';

const repoSchema = mongoose.Schema(
Expand Down Expand Up @@ -31,14 +30,13 @@ ObjectId.prototype.valueOf = function() {
return this.toString();
};

repoSchema.index({ 'ticks.date': 1 });
// repoSchema.index({ 'ticks.date': 1 });

const Repo = mongoose.model('Repo', repoSchema);

const reporefSchema = mongoose.Schema({
starsByDay: Number,
name: String,
});

const Reporef = mongoose.model('Reporef', reporefSchema);

function reduceRepo() {
Expand All @@ -48,56 +46,76 @@ function reduceRepo() {
for (var i = 0; i < lastTicks.length; i++) {
const t = lastTicks[i];
t.name = this.name;
t.id = this._id;
t.href = this.href;
t.language = this.language;
t.dates = t.date ? [t.date.toISOString().slice(0, 10)] : null;
// t.id = this._id;
// t.href = this.href;
// t.language = this.language;

// eslint-disable-next-line no-undef
emit(this._id, t);
}
}

function reduce(id, ticks) {
if (ticks.length < 2) {
return 0;
if (!ticks || ticks.length < 2) {
return null;
}

var tick = ticks[0];
var minStars = tick.stars;
var maxStars = minStars;
var minDate = tick.date;
var maxDate = ticks[ticks.length - 1].date;
var tmp = minStars;

for (var i = 1; i < ticks.length; i++) {
tmp = ticks[i].stars;
if (tmp > maxStars) {
maxStars = tmp;
} else if (tmp < minStars) {
minStars = tmp;
const maxIndex = ticks.length - 1;
const stars = ticks[maxIndex].stars;
const name = ticks[maxIndex].name; // only to be query
const speed = {};
const dates = [];

const stringDate = ticks[maxIndex].date.toISOString();
const date = stringDate.slice(0, 10);

// if (ticks.length === 1) {
// dates.push(date);
// return {
// name,
// date,
// dates,
// ticks,
// stars,
// speed,
// };
// }

for (var i = 0, ii = 1; i < maxIndex; i++, ii++) {
if (!ticks[ii].date) {
continue;
}
const stringDate = ticks[ii].date.toISOString();
const date = stringDate.slice(0, 10);
const hour = stringDate.slice(11, 16);
const time =
(new Date(ticks[ii].date).getTime() -
new Date(ticks[i].date).getTime()) /
86400000; // 3600000 * 24);
speed[date] = speed[date] || {};
speed[date][hour] = Math.round(
(ticks[ii].stars - ticks[i].stars) / time,
);

if (dates.indexOf(date) === -1) {
dates.push(date);
}
}

return {
date: maxDate,
stars: maxStars,
starsByDay: Math.round(
(24 * 1000 * 3600 * (maxStars - minStars)) /
(maxDate - minDate),
),
name,
date,
dates,
stars,
speed,
};
}

Repo.mapReduce(
{
map: map.toString(),
reduce: reduce.toString(),
query: {
'ticks.date': {
$gte: moment()
.subtract(24, 'hour')
.toDate(),
},
},
out: { replace: 'reporefs', inline: 1 },
},
(err, result) => {
Expand Down
7 changes: 4 additions & 3 deletions src/graphql/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,19 @@ export default gql`
name: String!
language: String!
description: String
starsByDay: Int
href: String!
Ticks: [Tick]
ticks: [Tick]
speed: JSON
stars: Int!
forks: Int!
date: Date
dates: [Date]
createdAt: Date!
updatedAt: Date!
}
type Query {
getRepos: [Repo]
getRepos(name: String, at: String, from: String, to: String): [Repo]
getRepo(id: ID!): Repo
}
Expand Down
2 changes: 1 addition & 1 deletion src/importer.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,5 +125,5 @@ module.exports = new CronJob({
});

if (process.env.NODE_ENV !== 'production') {
setTimeout(reduceRepo, 3000);
setTimeout(reduceRepo, 1000);
}

0 comments on commit 7c2e7e4

Please sign in to comment.