forked from bro-students/multy-stub
425 lines
9.9 KiB
JavaScript
425 lines
9.9 KiB
JavaScript
const { getDB } = require('../../../utils/mongo')
|
|
|
|
let db = null
|
|
|
|
// Database Name
|
|
const dbName = 'coder'
|
|
|
|
// Collections constant
|
|
const TOPIC_TAGS_COLLECTION = 'topic-tags'
|
|
const TOPIC_CATEGORIES_COLLECTION = 'topic-categories'
|
|
const TOPIC_LIST_COLLECTION = 'topic-list'
|
|
const TOPIC_COMMENTS_COLLECTION = 'topic-comments'
|
|
const USERS_COLLECTION = 'users'
|
|
|
|
// page size
|
|
const PAGE_SIZE = 2
|
|
|
|
// TODO убрать из export?
|
|
const connect = async () => {
|
|
db = await getDB(dbName)
|
|
}
|
|
|
|
const getCategories = async () => {
|
|
// TODO при первом запросе db = null
|
|
if (db === null) {
|
|
throw new Error('no db connection')
|
|
}
|
|
|
|
const collection = db.collection(TOPIC_CATEGORIES_COLLECTION)
|
|
|
|
const categories = await collection.find({
|
|
}).project({
|
|
_id: 0,
|
|
}).toArray()
|
|
|
|
if (categories.length === 0) {
|
|
const newCategories = require('./forum/categories.json').body
|
|
collection.insertMany(newCategories)
|
|
return newCategories
|
|
}
|
|
return categories
|
|
}
|
|
|
|
const getCategoryByPath = async (path) => {
|
|
if (db === null) {
|
|
throw new Error('no db connection')
|
|
}
|
|
|
|
const collection = db.collection(TOPIC_CATEGORIES_COLLECTION)
|
|
|
|
const category = await collection.findOne({
|
|
path,
|
|
}, {
|
|
projection: {
|
|
_id: 0,
|
|
},
|
|
})
|
|
|
|
if (!category) {
|
|
throw new Error('No data')
|
|
}
|
|
return category
|
|
}
|
|
|
|
const getTopicById = async (id) => {
|
|
if (db === null) {
|
|
throw new Error('no db connection')
|
|
}
|
|
|
|
const topicsCollection = db.collection(TOPIC_LIST_COLLECTION)
|
|
|
|
const topic = await topicsCollection
|
|
.aggregate([
|
|
{
|
|
$match: {
|
|
id: Number(id),
|
|
},
|
|
},
|
|
{
|
|
$limit: 1,
|
|
},
|
|
{
|
|
$lookup: {
|
|
from: USERS_COLLECTION, localField: 'authorId', foreignField: 'id', as: 'author',
|
|
},
|
|
},
|
|
{
|
|
$unwind: '$author',
|
|
},
|
|
{
|
|
$lookup: {
|
|
from: TOPIC_TAGS_COLLECTION, localField: 'tagsId', foreignField: 'id', as: 'tags',
|
|
},
|
|
},
|
|
{
|
|
$project: {
|
|
id: 0,
|
|
categoryId: 0,
|
|
authorId: 0,
|
|
tagsId: 0,
|
|
'author.id': 0,
|
|
'author._id': 0,
|
|
'tags.id': 0,
|
|
'tags._id': 0,
|
|
_id: 0,
|
|
},
|
|
},
|
|
])
|
|
.toArray()
|
|
|
|
if (topic.length === 0) {
|
|
throw new Error('No data')
|
|
}
|
|
|
|
return topic[0]
|
|
}
|
|
|
|
const getCommentsByTopicId = async (id, page) => {
|
|
if (db === null) {
|
|
throw new Error('no db connection')
|
|
}
|
|
|
|
if (page === undefined) {
|
|
page = 1
|
|
}
|
|
|
|
const commentsCollection = db.collection(TOPIC_COMMENTS_COLLECTION)
|
|
|
|
let count = await commentsCollection.count({
|
|
}, {
|
|
limit: 1,
|
|
})
|
|
if (count === 0) {
|
|
const newComments = require('./forum/topic-comments.json').body
|
|
commentsCollection.insertMany(newComments)
|
|
}
|
|
|
|
const comments = await commentsCollection
|
|
.aggregate([
|
|
{
|
|
$match: {
|
|
topicId: Number(id),
|
|
},
|
|
},
|
|
{
|
|
$skip: PAGE_SIZE * Number(page) - PAGE_SIZE,
|
|
},
|
|
{
|
|
$limit: PAGE_SIZE,
|
|
},
|
|
{
|
|
$lookup: {
|
|
from: USERS_COLLECTION, localField: 'authorId', foreignField: 'id', as: 'author',
|
|
},
|
|
},
|
|
{
|
|
$unwind: '$author',
|
|
},
|
|
{
|
|
$project: {
|
|
topicId: 0,
|
|
authorId: 0,
|
|
'author.id': 0,
|
|
'author._id': 0,
|
|
_id: 0,
|
|
},
|
|
},
|
|
])
|
|
.toArray()
|
|
|
|
// pagination
|
|
count = await commentsCollection.count({
|
|
topicId: Number(id),
|
|
})
|
|
const result = {
|
|
page,
|
|
pageSize: PAGE_SIZE,
|
|
total: count,
|
|
totalPages: Math.ceil(count / PAGE_SIZE),
|
|
comments,
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
const getTopicsByCategoryId = async (id, page) => {
|
|
if (db === null) {
|
|
throw new Error('no db connection')
|
|
}
|
|
|
|
if (page === undefined) {
|
|
page = 1
|
|
}
|
|
|
|
const topicsCollection = db.collection(TOPIC_LIST_COLLECTION)
|
|
|
|
let count = await topicsCollection.count({
|
|
}, {
|
|
limit: 1,
|
|
})
|
|
if (count === 0) {
|
|
const newTopics = require('./forum/topic-list.json').body.items
|
|
topicsCollection.insertMany(newTopics)
|
|
}
|
|
|
|
// TODO delete after auth implementation
|
|
const usersCollection = db.collection(USERS_COLLECTION)
|
|
const usersCount = await usersCollection.count({
|
|
}, {
|
|
limit: 1,
|
|
})
|
|
if (usersCount === 0) {
|
|
const newUsers = require('./forum/users.json').body
|
|
usersCollection.insertMany(newUsers)
|
|
}
|
|
|
|
const topics = await topicsCollection
|
|
.aggregate([
|
|
{
|
|
$match: {
|
|
categoryId: Number(id),
|
|
},
|
|
},
|
|
{
|
|
$skip: PAGE_SIZE * Number(page) - PAGE_SIZE,
|
|
},
|
|
{
|
|
$limit: PAGE_SIZE,
|
|
},
|
|
{
|
|
$lookup: {
|
|
from: USERS_COLLECTION, localField: 'authorId', foreignField: 'id', as: 'author',
|
|
},
|
|
},
|
|
{
|
|
$unwind: '$author',
|
|
},
|
|
{
|
|
$project: {
|
|
id: 1,
|
|
title: 1,
|
|
commentCount: 1,
|
|
viewCount: 1,
|
|
voteCount: 1,
|
|
creationDate: 1,
|
|
'author.name': 1,
|
|
'author.avatar': 1,
|
|
_id: 0,
|
|
},
|
|
},
|
|
])
|
|
.toArray()
|
|
|
|
if (topics.length === 0) {
|
|
throw new Error('No data')
|
|
}
|
|
|
|
// pagination
|
|
count = await topicsCollection.count({
|
|
categoryId: Number(id),
|
|
})
|
|
const result = {
|
|
page,
|
|
pageSize: PAGE_SIZE,
|
|
total: count,
|
|
totalPages: Math.ceil(count / PAGE_SIZE),
|
|
topics,
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
const getTags = async () => {
|
|
if (db === null) {
|
|
throw new Error('no db connection')
|
|
}
|
|
|
|
const tagsCollection = db.collection(TOPIC_TAGS_COLLECTION)
|
|
|
|
const count = await tagsCollection.count({
|
|
}, {
|
|
limit: 1,
|
|
})
|
|
if (count === 0) {
|
|
const newTags = require('./forum/topic-tags.json').body
|
|
tagsCollection.insertMany(newTags)
|
|
}
|
|
|
|
const tags = await tagsCollection.find({
|
|
}).project({
|
|
_id: 0,
|
|
}).toArray()
|
|
|
|
if (tags.length === 0) {
|
|
throw new Error('No data')
|
|
}
|
|
|
|
return tags
|
|
}
|
|
|
|
const findTags = async (value) => {
|
|
if (db === null) {
|
|
throw new Error('no db connection')
|
|
}
|
|
const tagsCollection = db.collection(TOPIC_TAGS_COLLECTION)
|
|
|
|
const tags = await tagsCollection
|
|
.find({
|
|
name: {
|
|
$regex: `${value}`,
|
|
},
|
|
})
|
|
.project({
|
|
_id: 0,
|
|
})
|
|
.toArray()
|
|
|
|
return tags
|
|
}
|
|
|
|
const insertTag = async (value) => {
|
|
if (db === null) {
|
|
throw new Error('no db connection')
|
|
}
|
|
const tagsCollection = db.collection(TOPIC_TAGS_COLLECTION)
|
|
// TODO no fast, reimplement
|
|
const count = await tagsCollection.estimatedDocumentCount()
|
|
|
|
await tagsCollection.insertOne({
|
|
id: count + 1,
|
|
name: value,
|
|
numTopics: 0,
|
|
})
|
|
|
|
return count + 1
|
|
}
|
|
|
|
const insertComment = async (comment) => {
|
|
if (db === null) {
|
|
throw new Error('no db connection')
|
|
}
|
|
const commentsCollection = db.collection(TOPIC_COMMENTS_COLLECTION)
|
|
// TODO no fast, reimplement
|
|
// TODO может перейти на _id?
|
|
const count = await commentsCollection.estimatedDocumentCount()
|
|
|
|
const currentTime = Math.round(new Date().getTime() / 1000)
|
|
|
|
await commentsCollection.insertOne({
|
|
id: count + 1,
|
|
topicId: comment.topicId,
|
|
voteCount: 0,
|
|
content: comment.content,
|
|
updationDate: currentTime,
|
|
creationDate: currentTime,
|
|
authorId: comment.authorId,
|
|
authorIsModerator: false,
|
|
isOwnPost: false,
|
|
})
|
|
|
|
return comment
|
|
}
|
|
|
|
const insertTopic = async (topic) => {
|
|
if (db === null) {
|
|
throw new Error('no db connection')
|
|
}
|
|
const topicsCollection = db.collection(TOPIC_LIST_COLLECTION)
|
|
// TODO no fast, reimplement
|
|
// TODO может перейти на _id?
|
|
const count = await topicsCollection.estimatedDocumentCount()
|
|
|
|
const currentTime = Math.round(new Date().getTime() / 1000)
|
|
|
|
const tagsId = []
|
|
|
|
if (topic.tags) {
|
|
for (let index = 0; index < topic.tags.length; index++) {
|
|
const tag = topic.tags[index]
|
|
if (tag.id === 0) {
|
|
const tagId = await insertTag(tag.name)
|
|
tagsId.push(tagId)
|
|
} else {
|
|
tagsId.push(tag.id)
|
|
}
|
|
}
|
|
}
|
|
|
|
const result = await topicsCollection.insertOne({
|
|
id: count + 1,
|
|
categoryId: topic.categoryId,
|
|
title: topic.title,
|
|
commentCount: 0,
|
|
viewCount: 0,
|
|
tagsId,
|
|
voteCount: 0,
|
|
voteStatus: 0,
|
|
content: topic.content,
|
|
updationDate: currentTime,
|
|
creationDate: currentTime,
|
|
authorId: topic.authorId,
|
|
isOwnPost: true,
|
|
})
|
|
|
|
if (!result.insertedId) {
|
|
throw new Error('Insert data failed, try again later')
|
|
}
|
|
|
|
return count + 1
|
|
}
|
|
|
|
module.exports = {
|
|
connect,
|
|
getTags,
|
|
findTags,
|
|
insertTag,
|
|
getCategories,
|
|
getTopicsByCategoryId,
|
|
getTopicById,
|
|
getCommentsByTopicId,
|
|
insertComment,
|
|
insertTopic,
|
|
getCategoryByPath,
|
|
}
|