CouchDB-river and related documents - couchdb

I have a product which is owned by a user in my CouchDB.
product =
name: 'Laptop'
userId: somelongid
user =
username: 'James'
With views and include_docs=true it returns:
product =
name: 'Laptop'
user =
username: 'James'
( I know it doesn't exactly return the above but it's close enough )
I do this cause every time I need a product I also need the owner (to link to his page). At first I thought I would just use include_document=true on the _change feed but of course that does something else.
So how can I get the related user when getting product results?

One solution is to collect all the userIds from the search result and query the _all_docs view in couchDb to get the users.

use a view (f.E. "userByDocId") that emits (doc._id,doc.user)
and do a query userByDocId?key="Username"

Related

Adding value to already declared MongoDB object with mongoose Schema

I am new to MongoDB and mongoose. I am trying to create a Node & MongoDB auction app. So since it is actually an online auction, users should be able to bid for items. I successfully completed the user registration, sign in page and authentication process, however, I am a bit stuck in the bidding page.
I created a Schema using mongoose and each item for auction is saved in the database. I want to add name and price of each user who bid for the item in the same object in MongoDB, like this:
{
name: "valuable vase from 1700s",
owner: "John Doe",
itemId: 100029,
bids: {
100032: 30000,
100084: 34000
}
}
So each user will have ids like 100032: 30000, and when they bid, their "account id: price" will be added under bids in the database object of the item.
I made some research and found some ways to solve the problem but I want to know if what I want to do is possible and if it is the right solution to do.
Thanks for giving me your time!
There are indeed couple of ways to achieve what you want.
In my opinion, a collection called ItemBids, where each document includes this data structure, will benefit you the most.
{
itemId: ObjectId # reference to the item document
accountId: ObjectId # reference to the account
bid: Number # the bid value
}
This pattern is suitable for your case because you can easily query the bids by whatever you want -
You can get all the account bids, you can get all the item bids, and you can sort them with native Mongo by the bid price.
Every time there's a bid, you insert a new document to this collection.
Another option is embedding an array of Bids objects in the item Object.
Each Bid object should include:
bids: [{
account: ObjectId("") # This is the account
price: Number
}]
The cons here are that querying it and accessing it will require more complex queries.
You can read more about the considerations
here:
https://docs.mongodb.com/manual/core/data-model-design
https://coderwall.com/p/px3c7g/mongodb-schema-design-embedded-vs-references
The way you decided to implement your functionality is a little bit complicated.
It is not impossible to do that but, the better way is to use array of objects instead of a single object like this:
{
name: '',
..
..
bids: [{
user: 100032,
price: 30000
}, {
user: 100084,
price: 34000
}]
}

Saving data on object for each user in a nosql database (Mongo)

I have a REST API which serves from a database in MongoDB. Say each JSON unit that is served contains data about a film. I'd like my users to tick whether they've seen a film or not. My problem is that, being a beginner, I am not sure how this should be implemented.
I somehow need to save this for each user. Right now my mongo database just holds all of the films in general.
Could you give me an example of how this would be accomplished in a no-sql database? What if I want to save more detailed data like when a user takes private notes related to a certain film?
You can simply have a table that has the user_id, the movie_id and the boolean, which mean if there is movie_id and a user_id the boolean is true if not it remains false thats how i would impplement it.
You can have movies data some what like this which contains unique ID for each movie
movie={
id : <MOVIE_ID> //some movie ID
name : <MOVIE_NAME> //some name
... //other info you want to store
}
then you can save each movie that user had watched in his user data in a array
user = {
id : <USER_ID> //some user id
name : <USER_NAME> //some name
watched_movies : [<MOVIE_ID1>,<MOVIE_ID2>,.....] //movie IDS
... //other data about user
}
while you rendering all movies for particular user you just need to traverse these array and mark check for movie if user have already watched that movie

How can I count the view of a Specific post by a User ? Count every User just Once

We have user and news model, in the news model we have e viewsCount field, I want to increment this view count when a GET request is made by a User.
When a specific user makes a GET request, the view count will increment one, every user just one view.
const NEWSModel = new Schema({
viewesCount: { type: Number },
Publisher: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true
},
LikesCount: { type: Number },
DislikeCount: { type: Number },
Comments: CommenTs
});
Every user can view the news as many times as wants, but just can make one view. How can I do that?
you Can change your model like and then whenever you get a news just push the user id to the viewedBy field.
news.viewedBy.push(user id)
viewedBy: [{
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}]
}); ```
If you have not a lot of users, you can add additional field to news model like users_viewed which would be array of unique user ids.
And make additional check before incrementing views count.
If user, who requested news is already in this users_viewed array, you skip any additional actions.
If don't, increment views counter.
But if you do have a lot of users, it's better to store views counter in Redis to skip request to database and increment in memory counter.
The logic for storing and showing data would be the same, but you'll reduce load on your database and speed up the whole process.
[UPDATE] According to your comment, about number of users.
To make things work you can use this package.
First of all, after request for a news from a client, you can store all the news data in your cache (to reduce number of requests to your database).
Now you have few possible ways to handle number of views.
I think, the easiest to implement would be to add user unique identifier to SET. And return number of users in SET using SCARD;
In this solution you wouldn't need to check if user already watched the news, because set data structure holds only unique values (the same reason why do we need to use user's unique identifier).
And you just use 2 redis requests, which is pretty good for heavy load services.
You can have another field called viewedBy of type array in which you can store users ids. Then it will be easier to check if a user already viewed your post or to count them.
File: news.model.js
const News = new Schema({
viewedBy: [{
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}],
// other properties...
});
File: news.controller.js
const user = User.find({...}); // get current user
const news = News.find({...}); // get a news
/*
Update views count by adding the current user id if it's not already added
Thanks to '$addToSet', the update() function will do nothing if the user id it's already there)
*/
news.update({ $addToSet: { viewedBy: user._id } });
// Getting the views count
console.log('Total views:', news.viewedBy.length);
More about $addToSet: https://docs.mongodb.com/manual/reference/operator/update/addToSet/

Can there be two embedded mongoose documents with one schema?

Let's say I have for example:
const Stats = Item({
name: String,
value: Number
})
const Player = Schema({
name: String,
objectInventory: [Item],
petInventory: [Item]
})
Would the items somehow get mixed up? Is this safe? Are all the items unique and know where they belong to? I don't want to write Player.objectInventory and get pets in there. I'm sorry if this seems like common sense but I had that doubt.
Yes there can be two documents in one schema. This items will not get mixed up. The mongoose is nothing more than just another layer on top of the database to help you with schema. So in your case, you would just put different ids for different properties (e.g. objectInventory and petInventory) and when you would populate them, the mongoose will just make correct queries to return the results.

Retrieving posts with user information in rethinkdb

Im working on some sort of social network in which people are able to make posts about a topic and like them.
Im having trouble tracking user likes.
The schema is the following:
Users:
{ userId: "someId", likes: ["idPost1", "idPost4", ...] }
Posts:
{ postId: "someId", topic: "idTopic", postContent: "someContent"}
I need a query that can:
Take all posts from a certain topic, like this:
r.table('posts').filter({
topic: idTopic
}).run().then( posts => res.json(posts))
Look up to see if the current user (given by the user id) has liked any of the posts on that specific topic. Then return a JSON with all posts on that topic, and those liked by the user with "liked: true".
Im having trouble with step 2,
Please let me know if im modelling data the wrong way, or if you can think of any way I can accomplish step 2.
Thanks!
This function does what you're looking for in javascript. (Tested using the Data Explorer)
r.db("test").table('posts').filter({ topic: "idTopic" }).merge(function(post){
return {liked: r.table('users').filter({userId: "someId"})(0)('likes').contains(post("postId")) }; })
The merge function basically iterates every post and adds the field liked to it. The contains function checks whether the posts id is in the likes array and return in directly as truth value.

Resources