Get a list of common friends between more than 2 users in graph database - titan

I am working with Titan graph database (v1.0), and I am looking for gremlin query to find the mutual friends between more than 2 users. Suppose I have a "user1", "user2", and "user3". I want to find the mutual friends between these 3 users. I know that the following query will give me the mutual friends between "user1" and "user2", but how can I find the mutual friends between more than 2 users? I know for two users I can use the following query:
g.V(user1).both("friend").where(both("friend").is(eq(user2)))
What about more than 2 users? I know I can do the same with all pairs, but this is not an efficient query!

The match() step will probably be your best choice as it's the easiest to read and write. Might not be the fastest though.
g.V().has("name","user1").as("u1").
V().has("name","user2").as("u2").
V().has("name","user3").as("u3").
match(
__.as("u1").both("friend").as("f"),
__.as("u2").both("friend").as("f"),
__.as("u3").both("friend").as("f")
).where("f", neq("u1").and(neq("u2")).and(neq("u3"))).select("f")
Here's the query in action: http://www.gremlinbin.com/bin/view/570a30f9a58c9
Alternatively (without mid-traversal V()'s and without the where() conditions) you could do:
g.V().has("name","user1").both("friend").and(
both("friend").has("name","user2"),
both("friend").has("name","user3"))

Related

What would be the best way to count demographics from DB? Mongoose+MongoDB

I would like to present in my application's admin-pannel a count of the users demographics.
For example:
United States: 500 users
United Kingdom: 241 users
India: 2141241221 users.
Israel: 1 user.
Since there are a lot of countries in the world, I don't want to start searching for each country specifically. I would like to run one search that will count how many times each country appeared. I can't think of an idea that would not require me to search for countries specifically.
Example of what I do NOT want to do:
mongoose.find({Country: India}).then((documents) => { console.log("documents.length")} )
Using this method will require me to write the same line for each country that exists, and I'm sure theres a better way to go about it.
Use Mongodb Aggregation $group stage to achieve this.

Efficiently find users using $near and excluding those who have disliked the user

Here is the assumed schema I think is the best to put into place
Users
userId
first_name
age
gender
location (lat,lon)
Matches
userId (voter)
like (vote)
liked_UserId
I know how to find users using the near parameter:
db.users.find({loc: {$near:[-180,40]}}).limit(3)
BUT
1) I'm trying to figure out the best and efficient way of finding users who are the closest and excluding users who have disliked this user. Should I make two query calls??? maybe a $where clause from the other collection somehow?
Edit: I'm thinking make one query to get all the users who have disliked this certain user, then add this array of users as part of a second query in the $nin...but will that be very slow if there are over 400,000 entries?
2) Does Tinder show the user of a profile of another user that disliked them?

Query moongoDB from a redis list

If for example I keep lists of user posts in redis, for example a user has 1000 posts, and the posts documents are stored into mongodb but the link between the user and the posts is stored inside redis, I can rtetrieve the array containing all the ids of a user post from redis, but what is the efficient way to retrieving them from mongodb?
do I pass a parameter to mongoDB with the array of ids, and mongo will fetch those for me?
I don't seem to find any documentation on this, if Anyone is willing to help me out!
thanks in advance!
To retrieve a number of documents per id, you can use the $in operator to build the MongoDB query. See the following section from the documentation:
http://docs.mongodb.org/manual/reference/operator/query/in/#op._S_in
For instance you can build a query such as:
db.mycollection.find( { _id : { $in: [ id1, id2, id3, .... ] } } )
Depending on how much ids will be returned by Redis, you may have to group them in batch of n items (n=100 for instance) to run several MongoDB queries. IMO, this is a bad practice to build such query containing more than a few thousands ids. It is better to have smaller queries but accept to pay for the extra roundtrips.

Mongodb Aggregate: Nested totals

I am trying to generate a report from our mongo db that tallies up the unique visits by country code per referral site. I'd like to use aggregation as I've heard it is quite fast and performance here is an issue.
We have an account db that has a country code and last referral site associated with each account.
{
account:"user123",
CountryCode:"CA",
ReferalSite:"Google",
lastLogin:"someisodate"
}
Conceptually, I can write the javascript in a few minutes.
For each unique vistor in accounts db;
visits[vistor.country_code][vistor.refferal_site]+= 1;
Is this query possible with a db.accounts.aggregate()? Or is a map/reduce the better way to go about this.
Thanks in advance,
You can run two groups one after another :
db.collection.aggregate([
{$group:{_id:{account:'$account', CountryCode:'$CouintryCode', ReferalSite:'$ReferalSite'}}, {number:1}},
{$group:{_id:{CountryCode:'$_id.CountryCode', ReferalSite:'$_id.ReferalSite'}}, {number:{$sum:'$number'}}}])

mongodb - add column to one collection find based on value in another collection

I have a posts collection which stores posts related info and author information. This is a nested tree.
Then I have a postrating collection which stores which user has rated a particular post up or down.
When a request is made to get a nested tree for a particular post, I also need to return if the current user has voted, and if yes, up or down on each of the post being returned.
In SQL this would be something like "posts.*, postrating.vote from posts join postrating on postID and postrating.memberID=currentUser".
I know MongoDB does not support joins. What are my options with MongoDB?
use map reduce - performance for a simple query?
in the post document store the ratings - BSON size limit?
Get list of all required posts. Get list of all votes by current user. Loop on posts and if user has voted add that to output?
Is there any other way? Can this be done using aggregation?
NOTE: I started on MongoDB last week.
In MongoDB, the simplest way is probably to handle this with application-side logic and not to try this in a single query. There are many ways to structure your data, but here's one possibility:
user_document = {
name : "User1",
postsIhaveLiked : [ "post1", "post2" ... ]
}
post_document = {
postID : "post1",
content : "my awesome blog post"
}
With this structure, you would first query for the user's user_document. Then, for each post returned, you could check if the post's postID is in that user's "postsIhaveLiked" list.
The main idea with this is that you get your data in two steps, not one. This is different from a join, but based on the same underlying idea of using one key (in this case, the postID) to relate two different pieces of data.
In general, try to avoid using map-reduce for performance reasons. And for this simple use case, aggregation is not what you want.