Database query for events based on friends going - sql

I'm trying to build a timeline with events for users.
To build this timeline, I would run a query that does the following:
returning all events where friends of the user are set to going.
What I have now:
client-side: a List of all the ids of the friends of a user: ex. ['a', 'b', 'c', 'd', 'e']
server-side: a Firestore collection with all the events:
events/eventID
This document has a value 'going' which is a list that contains all the users IDs that are 'going' ex. ['d', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm']
(As an example, the query should return this document, because 2 friends are going)
A simple solution would be:
Getting all events and comparing the 2 lists on the client-side. Problem: ok for 100 documents, but impossible if the collection scales. (Because Firstore bills on document reads.)
Is there a better way to do this (With Firestore)?
Or is this not possible with Firestore and are there other technologies to do this?
Thanks in advance!

There's no code in the question and I don't know the platform so let me answer this at a high level.
Suppose we have a users collection:
users
uid_0
name: Larry
friends:
uid_1: true
uid_2: true
events_where_friends_are_going:
event_0:
uid_1: true
uid_2: true
uid_1
name: Moe
friends:
uid_2: true
events_where_friends_are_going:
event_0:
uid_2: true
uid_2
name: Curly
and let's say we have a series of events stored in a collection:
events
event_0
name: "some event"
signups:
uid_1: true
uid_2: true //Curly signed up
The process is that when a user signs up for an event, event_0 for example, they are added to that event collection and then query the users collection for all of the other users they are friends with via the friends sub-collection. Then they add themselves to the events_where_friends_are_going, creating the event if it doesn't exist, or if it does, add themselves to the list.
In the above structure, if Curly signed up for event_0, as shown in the signups collection, the query reveals they are friends with uid_0 and uid_1. They are then added to uid_0 and uid_1 events_where_friends_are_going collection.

Related

i18next-scanner using keys with variables

I have a list x = ['a', 'b', 'c'] and load translations using t(vars.${x[i]}).
When I used i18next-scanner, I get a records under vars with key "".
I have already defined in comments, e.g., // t('vars.a'); , so this is picked up by the scanner. How can I eliminate so that i18next-scanner does not also add an empty key?

get grouped results with sparql query

I still feel like a SPARQL newbie, so I may be way off base about what SPARQL GROUP BY does, but here's my questions.
Suppose I wanted to request all resources in graph database called Categories, and I wanted to get all the items associated with these categories, along with the names of the items and their price.
Right now my SPARQL queries are giving me back something like the following table:
**Categories Item ItemName ItemPrice**
Tools HammerID Hammer $12
Tools SawID Saw $13
Tools WrenchID Wrench $10
Food AppleID Apple $5
Food CornID Corn $1
I wanted to use GROUP BY to group the items under a single category, so that when I start processing it, I can look through each unique category and then display the items that belong in that category.
Right now if I loop through the above results, I will be iterating over 5 entries instead of 2.
The other way I can describe the results I want are by imaging what the corresponding json data would look like. I want something like:
[
tools: [
{id: hammerId
title: hammer
price: $12},
{id: sawId
title: saw
price: $13},
{id: wrenchId
title: wrench
price: $10}
],
food: [
{id: appleId
title: apple
price: $5},
{id: cornId
title: corn
price: $1}
]
]
With the results, like this I can directly loop over the top level items, and then display the results for each.
Can I use GROUP BY to tell SPARQL to give me results like this?
No, you can't. A SPARQL SELECT query-result is defined as a sequence of solutions, with each solution being a set of variable-value pairs (with a value being defined as an IRI, BNode, or literal value). Basically it's a simple table. There is no provision for 'nested' solutions like you'd need for your JSON-like structure.
However the difference is purely syntactic. If you group, you know the result will deliver all solutions belonging to the same group together (one after the other) - so in processing the result you can simply treat the grouped variable as a marker. And of course if you really want, you can easily rewrite the query result into this kind of syntactic structure yourself - it's just a different way of writing down the exact same information, after all.

How to perform a conditional count in a Rails active record query?

In a Rails 3.2 app I'm trying to construct a query that will return an array with two calculated counts. The app has three models: a User has many Events, and a Location has many Events. I need to return an array for a user that contains the number of events they have at each location, as well as the number of active events.
e.g., [#<Location id: 1, name: "Location Name", total_events_count: 4, active_event_count: 4>]>
I can get the total_event_count
user = User.find(params[:id])
user.locations
.select("locations.id, locations.name, count(events.id) AS total_events_count")
.joins(:events)
.group("locations.id")
Given that my Event model has a string status field that can take a value active, how would I also include an active_events_count in this query?
EDIT
After some useful suggestions from xdazz and mu, I'm still struggling with this. My problem appears to be that the count is counting all events, rather than events that belong to the location AND the user.
I'm going to try to rephrase my question, hopefully someone can help me understand this.
Events belong to both a User and a Location (i.e. User has_many :locations, through: :events)
Events have several fields, including status (a string) and participants (an integer).
In a User show view, I'm trying to generate a list of a User's locations. For each location, I want to display a "success rate". The success rate is the total number of a User;s events with participants, divided by the total number of that User's events. i.e., if User1 has 4 events at LocationA, but only two of those events had participants, User1's success rate at LocationA is 0.5 (or 50%).
The way I though to achieve this is via a select query that also includes calculated counts for total_events_count and successful_events_count. (there may be a better way?)
So I do something like:
user = User.find(params[:id])
user.locations
.select("locations.id, locations.name, count(events.id) AS total_events_count, sum(case events.marked when NOT 0 then 1 else 0 end) AS successful_events_count")
.joins(:events)
.group("locations.id")
This is returning an array with the correct keys, but the values are not correct. I am getting the total number of all events (and all successful events) for that location, not just a count of those events that belong to the current user.
I have been looking at this problem for so long that I'm getting myself very confused. Would be very grateful for a fresh perspective and ideas!!
EDIT2
After a break and fresh eyes, I have managed to get the result I need using the following code. It seems quite convoluted. If there is a better way, please let me know. Otherwise I will tidy up this question in case anyone else runs into the same problem.
class User
def location_ratings
events = self.events
successful_events = events.where('events.participants > 0')
user_events_by_location = Event.
select("events.location_id AS l_id, count(events.id) AS location_event_count").
where( id: events.pluck(:id) ).
group("l_id").
to_sql
user_successful_events_by_location = Event.
select("events.location_id AS l_id, count(events.id) AS location_successful_events_count").
where( id: successful_events.pluck(:id) ).
group("l_id").
to_sql
Location.
joins("JOIN (#{user_events_by_location}) AS user_events ON user_events.l_id = location.id").
joins("JOIN (#{user_successful_events_by_location}) AS successful_user_events ON successful_user_events.l_id = location.id").
select('location.id, location.name, user_events.location_events_count, successful_user_events.location_successful_events_count').
order("user_events.location_events_count DESC")
end
You could use sum(events.marked='active') to get it:
user.locations
.select("locations.id, locations.name, count(events.id) AS total_events_count, sum(events.marked='active') AS marked_event_count")
.joins(:events)
.group("locations.id")
Update:
If you are using postgresql, then you have to case boolean to int before using SUM function.
user.locations
.select("locations.id, locations.name, count(events.id) AS total_events_count, sum((events.marked='active')::int) AS marked_event_count")
.joins(:events)
.group("locations.id")

Redis - subset of querying hashes and then sorting alphabetically on a value of the hash

In my application users can favourite pages - I store these in a set
user:123:favourites
456, 671, 106, 507, 789
I also store a hash of information for each page
page:1
title: "foo"
owner_name: "jim"
page:2
title: "bar"
owner_name: "tim"
....
page:n
title: "title-n"
owner_name: "owner-n"
I'm trying to do the following
Get the set of favourite pages
Get the page objects from the hashes
Sort the page hashes by title
Return a subset of the pages (for paging results - 1-3 or 4-6)
I'm still quite new to redis so kind of struggling to get my head around if this is possible and if I should even be using redis this way.
What steps here should be completed on the redis side and what steps should be completed on the application side?
Here's my guess, I'll try it later
SORT user:123:favourites BY page:* -> title GET # LIMIT 0 2 ALPHA DESC

eBay API categoryId in findItemsAdvanced call returns wrong categories

I'm trying to use the categoryId in my findItemsAdvanced query:
api.execute('findItemsAdvanced', {
'keywords': 'laptop',
'categoryId': '51148'}
The results I get are, for example (printing the searchResult dictionary):
'itemId': {'value': '200971548007'}, 'isMultiVariationListing': .............
'primaryCategory': {'categoryId': {'value': '69202'}, 'categoryName': {'value': 'Air Conditioning'}}
....."
You can see that the result has a categoryId of 69202, and not 51148.
What am I doing wrong here? I'm just using the finding.py code at:
https://github.com/timotheus/ebaysdk-python
Thanks
Edit
I've done some tests. I extracted the XML that the SDK builds. If I call with:
'categoryId': '177'
The response is:
the request_xml is <?xml version='1.0' encoding='utf-8'?><findItemsAdvancedRequest
xmlns="http://www.ebay.com/marketplace/search/v1/services"><categoryId>177</categoryId>
<itemFilter><name>Condition</name><value>Used</value></itemFilter><itemFilter>
<name>LocatedIn</name><value>GB</value></itemFilter><keywords>laptop</keywords>
<paginationInput><entriesPerPage>100</entriesPerPage><pageNumber>1</pageNumber>
</paginationInput></findItemsAdvancedRequest>
and I get the same with
'categoryId': ['177']
I find this a bit odd, I thought the appropriate name for the XML categoryId was 'CategoryId' with a capital C. If I do that I don't get an error, but the result is not restricted to the categoryId requested.
Doing it like above, I still get the error:
Exception: findItemsAdvanced: Domain: Marketplace, Severity: Error,
errorId: 3, Invalid category ID.
The code below will do a keyword search for 'laptops' across the UK eBay site and restrict the search to the two categories Apple Laptops(111422) and PC Laptops & Netbooks(177). In addition the results are filtered to only show the first 25 used items that are priced between £200 and £400. The results are also sorted by price from high to low.
There are a few things to keep in mind about this example.
It assumes that you have already installed ebaysdk-python.
According to the eBay docs the categoryId field is a string and more than one category can be specified. An array is therefore used to hold the category ids that we are interested in.
Our request needs to search for items in the UK eBay site. We therefore pass EBAY-GB as the siteid parameter.
Category ids are different across each eBay site. For example the category PC Laptops & Netbooks(177) does not exist in Belgium. (Which incidently is the site that is used in the ebaysdk-python finding.py example.)
This example is also available as a Gist
import ebaysdk
from ebaysdk import finding
api = finding(siteid='EBAY-GB', appid='<REPLACE WITH YOUR OWN APPID>')
api.execute('findItemsAdvanced', {
'keywords': 'laptop',
'categoryId' : ['177', '111422'],
'itemFilter': [
{'name': 'Condition', 'value': 'Used'},
{'name': 'MinPrice', 'value': '200', 'paramName': 'Currency', 'paramValue': 'GBP'},
{'name': 'MaxPrice', 'value': '400', 'paramName': 'Currency', 'paramValue': 'GBP'}
],
'paginationInput': {
'entriesPerPage': '25',
'pageNumber': '1'
},
'sortOrder': 'CurrentPriceHighest'
})
dictstr = api.response_dict()
for item in dictstr['searchResult']['item']:
print "ItemID: %s" % item['itemId'].value
print "Title: %s" % item['title'].value
print "CategoryID: %s" % item['primaryCategory']['categoryId'].value
I hope the following will explain why performing a search on the Belgium site results in items that contain the category 177 even though this is not valid for Belgium but is valid for the UK.
Basically eBay allow sellers from one site to appear in the search results of another site as long as they meet the required criteria, such as offering international shipping. It allows sellers to sell to other countries without the need to actually list on those sites.
From the example XML that elelias provided I can see that a keyword search for 'laptop' was made on the Belgium site with the results filtered so that only items located in the UK was to be returned.
<itemFilter>
<name>LocatedIn</name>
<value>GB</value>
</itemFilter>
Because the search was limited to those located in the UK you won't see any Belgium items in the results. Since the items where listed on the UK site they will contain information relevant to the UK. For example the category id 177. eBay does not convert the information to make it relevant to the site that you are searching on.
It is important to remember that what ever you are trying to do with the Finding API can also be repeated using the actual advance search on eBay. For example it is possible to re-create the issue by performing a keyword search for used items on the Belgium site.
This url is the equivalent of your code that was performing the search without specifying the category 177. As you can see from the results it returns items that where listed on the UK site but which are appearing in the Belgium site. It you click on some of the items, for example, you can even see that it displays the UK category PC Laptops & Netbooks (177) even though this does not exist on the Belgium site. This matches the results form your code where it was returning 177 but would not let you specify the same value in the request as you was searching the Belgium site.
I hope this helps.
Because categoryId is repeatable. You will need to pass an array into the call. Something like this should work.
api.execute('findItemsAdvanced', {
'keywords': 'laptop',
'categoryId': [
{'51148'}
]
}
Note: See how the itemFilter element is an array in the sample file of the SDK.
'itemFilter': [
{'name': 'Condition',
'value': 'Used'},
{'name': 'LocatedIn',
'value': 'GB'},
],