facebook open graph api - filter node collection by field - facebook

At a high level, what I'm looking for is all of the posts a specific user has made in a group.
I can access the group feed, which contains all posts made in the group, like this:
GET 2.10/<group-id>/feed
where 2.10 is the api version I am using
I can see the author of all the posts in the feed by reading the "from" field:
GET 2.10/<group-id>/feed?fields=from
the "from" field displays a user, which is represented as a JSON object with two properties:
"from": {
"name": <user_name>,
"id": <user_id>
}
some collections have "read modifiers", for example on a feed that belongs to a person's profile, you can filter for only posts that have locations attached to them:
GET 2.10/me/feed?with=location
It seems a "read modifier" on the group feed would be what is needed, however none are documented: https://developers.facebook.com/docs/graph-api/reference/v2.10/group/feed
Is there any way to filter the feed so that it returns only posts by a specific author?
rephrased more generally:
is it possible to filter a collection of nodes by a node attribute?
is there another possible way to query for posts made by a specific person in a specific group?

Related

How can i search events by description field using Graph API?

I'm trying to list all upcoming events for a given artist. Unfortunately, the query that i use:/search?type=event&fields=name,description,place&q=artist-name does not list all available events. It only lists the events for which the keyword "artist-name" match the field "name". To display all available events, the query must look into the "description" field in addition to the "name". How can i make such a query ?

Schema on mongodb for reducing API calls with two collections

Not quite sure what the best practice is if I have two collections, a user collection and a picture collection - I do not want to embed all my pictures into my user collection.
My client searches for pictures under a certain criteria. Let's say he gets 50 pictures back from the search (i.e. one single mongodb query). Each picture is associated to one user. I want the user name displayed as well. I assume there is no way to do a single search performance wise on the user collection returning the names of each user for each picture, i.e. I would have to do 50 searches. Which means, I could only avoid this extra performance load by duplicating data (next to the user_id, also the user_name) in my pictures collection?
Same question the other way around. If my client searches for users and say 50 users are returned from the search through one single query. If I want the last associated picture + title also displayed next to the user data, I would again have to add that to the users collection, otherwise I assume I need to do 50 queries to return the picture data?
Lets say the schema for your picture collection is as such:
Picture Document
{
_id: Objectid(123),
url: 'img1.jpg',
title: 'img_one',
userId: Objectid(342)
}
1) Your picture query will return documents that look like the above. You don't have to make 50 calls to get the user associated with the images. You can simply make 1 other query to the Users Collection using the user ids taken from the picture documents like such:
db.users.find({_id: {$in[userid_1,user_id2,userid_3,...,userid_n]}})
You will receive an array of user documents with the user information. You'll have to handle their display on the client afterwards. At most you'll need 2 calls.
Alternatively
You could design the schema as such:
Picture Document
{
_id: Objectid(123),
url: 'img1.jpg',
title: 'img_one',
userId: Objectid(342),
user_name:"user associated"
}
If you design it this way. You would only require 1 call, but the username won't be in sync with user collection documents. For example lets say a user changes their name. A picture that was saved before may have the old user name.
2) You could design your User Collection as such:
User Document
{
_id: Objectid(342),
name: "Steve jobs",
last_assoc_img: {
img_id: Object(342)
url: 'img_one',
title: 'last image title
}
}
You could use the same principles as mentioned above.
Assuming that you have a user id associated with every user and you're also storing that id in the picture document, then your user <=> picture is a loosely coupled relationship.
In order to not have to make 50 separate calls, you can use the $in operator given that you are able to pull out those ids and put them into a list to run the second query. Your query will basically be in English: "Look at the collection, if it's in the list of ids, give it back to me."
If you intend on doing this a lot and intend for it to scale, I'd either recommend using a relational database or a NoSQL database that can handle joins to not force you into an embedded document schema.

Designing mongo 'schema' for RESTful application

I'm trying to teach myself mongo through writing an application, and I'm struggling with the best way to design the mongo 'schema' (I know it's schemaless, but that is probably the core issue with my understanding in that I'm coming from a relational background)
Anyway, the application is a Gift List manager, where a user can create a Gift List and can add Gifts they would like to receive to their list. Other users can subscribe to the list, and can mark a Gift from the Gift List as claimed/purchased. (So as to prevent the problem of getting duplicate gifts at Christmas!)
At the moment my GiftLists collection is not 'relational' and is simply a collection of GiftList documents with sub documents for the Gifts, like this:
{
"GiftLists": [
{
"_id": {
"$oid": "55e9924848c4ffd723890b48"
},
"description": "Xmas List for Some User",
"gifts": [{
"description": "Mongo book"
"claimed": false
},
{
"description": "New socks"
"claimed": false
},
{
"description": "New socks"
"claimed": false
}],
"owner": "some.user",
"subscribers": ["some.other.user", "my.friend"]
}
]
}
The idea is that some.user is the owner of the Gift List and has added 3 items he would like to receive. some.other.user has subscribed to the list and can see the Gift List and it's Gifts. He may choose to buy one of the gifts, so needs to mark it as claimed so that my.friend does not also buy it.
At the moment, each Gift in the gifts array is a sub-document without its own id, and I think this is where I'm getting stuck in my understanding/thinking.
I'm trying to provide the app functionality with a RESTful interface.
To POST a new Gift List the url is /giftList/add where the request body is the new Gift List
To GET an individual Gift List including the child Gift's the url is /giftList/<listId> - eg: /giftList/55e9924848c4ffd723890b48
With the above in mind, my natural next step is to be able to mark a Gift as claimed, perhaps with:
PUT to the url /gift/claim/<giftId>
But I don't have any ids on the Gift sub documents
So maybe my url should be:
/giftList/<listId>/claim/<giftId>
But again, I don't have an id on the Gift sub document
Or maybe I try to use the description of the item
/gift/claim/<gift description> eg: /gift/claim/Mongo+book
But what if more than one person had a Gift List containing 'Mongo book', and URL encoding the characters of the description could be messy
Or maybe I reference the Gift List
/giftList/<listId>/claim/<gift description> eg: /giftList/55e9924848c4ffd723890b48/claim/New+socks
But which instance of 'New socks' am I claiming? (after all, everyone needs lots of new socks for Christmas!)
Or maybe I reference the index of the Gift
/giftList/<listId>/claim/<gift index> eg: /giftList/55e9924848c4ffd723890b48/claim/2
But this feels fragile (as it implies that the list must always be presented in the same sequence)
To me what it really feels like is that I need another collection, just for the Gifts, where each Gift document has its own id, which I can then reference in my RESTful url. And either the Gift has a reference to it's parent GiftList, or the GiftList has an array of references to the Gifts
But this is all a very 'relational' way of thinking ... isn't it ?
What's the best way of doing this? Or, if there is no 'best' way, what are my options?
You could solve this with a new collection, or you could add an unique identifier field to each list entry. The MongoDB solution for unique identifiers is generating an ObjectId, just like those used for the _id field of documents. Most MongoDB database drivers should expose functionality for generating ObjectId's. For details, consult the documentation of your database driver.

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.

Relationships in MongoDB

On a new project I've decided to go with mongodb for the main database, but my inexperience with it has led to some confusion in how I should structure the relationships between different collections.
In my case I have a users collection, a 'notes' collection and a groups collection. Notes can be open to different users and groups. If a user is part of a group and that group has read access to the note, then so does the user. If the user is removed from the group, then they no longer have access to the note. However, a user may have access to the note on a user basis, and even if they are removed from a group with access, they can still see the note. Hopefully that makes sense.
The problem I'm facing is setting up the permissions so that all of this is possible. Should the permissions be stored in the notes collection? If its stored as follows:
note: {id: xxxx, followers:[{id:user1, permission:write},{id:groupA, permission:read}]}
Then in the case that a user2 is part of groupA, I would need to check to see if they are associated with the node by their id, and if not, I will have to check each group that can see that note and look at their members, and if different groups have different permissions, I have to take the highest permission. This doesn't seem efficient.
The users collection looks like this:
user: {id:user1, projects:[xxxxx, xxxxx], groups:[xxxxx,xxxx...]}
The groups collection:
group: {id:groupA, projects:[xxxxx, xxxx...], users:[user2...]}
I was planning on linking the group documents with the project and user documents so that if the group is removed from a project, the project would be removed from the group. It seems like a dbref is the best way to do this.
I've looked through best practices and I feel like the overall structure I have is messy, but I can't think of another way to do it.
Given your requirements, if groups have more users than users have groups then you should consider storing group_ids within a user.
You could combine users and groups into one collection that had two different schemas and something like an is_group attribute but conceivably there could one day be collection level locking and the below would give you more flexibility.
To figure out if a user has access you would only need to query the project collection and see whether the group ids they are members of are within the write or read arrays after the project document is retrieved.
Project:
{
"_id": ObjectId,
"write": [group_id, group_id, ...],
"read": [group_id, group_id, ...]
}
User:
{
"_id": ObjectId,
"groups": []
}
Group:
{
"_id": ObjectId,
}