In Factual how to get results with unique field values (similar to GROUP BY in SQL)? - factual

I've just set out on the path to discovery of Factual API and I cannot see how to achieve a retrieval of a selection of entries each with a unique value in the specified field.
For example, give me 10 results from various cities:
q.limit(10);
q.field("locality").unique(); // no such filter exists
factual.fetch("places", q);
This would be an equivalent query in MySQL:
SELECT * FROM places GROUP BY locality LIMIT 10;
What I want is a little bit similar to facets:
FacetQuery fq = new FacetQuery("locality").maxValuesPerFacet(10);
fq.field("country").isEqual("gb");
FacetResponse resp = factual.fetch("places", fq);
but instead of the total for each result I would like to see a random object with all the information.
Is anything like this possible?

Related

Handling multiple search fields in cypher or py2neo

Just getting started with cypher. Trying to understand best way to handle this case. I need to query database based on several search fields(not always present). Wondering what's the best way to handle it. For e.g I collect data from html post request
storeName = request.form['storeName']
storeCountry = request.form['storeCountry']
storeState = request.form['storeState']
storeCity = request.form['storeState']
I'm using flask framework, so defined this function with py2neo to handle search fields. Not sure if I got it right but if all fields are set correctly, hopefully, something like this should work fine
def get_search_results(skipNumber,limitNumber, storeName, storeCountry,storeState, storeCity):
query = """
MATCH (store:store) WHERE store.name = {storeName}
MATCH (store:store)-[:IS_IN_COUNTRY]->(c:Country) WHERE c.name = {storeCountry}
MATCH (store:store)-[:IS_IN_STATE]->(s:State) WHERE s.name = {storeState}
MATCH (store:store)-[:IS_IN_CITY]->(ct:City) WHERE ct.name = {storeCity}
RETURN user SKIP {skip} LIMIT {limit}
"""
return graph.cypher.execute(query, skip=skipNumber, limit=limitNumber, storeName=storeName, storeCountry=storeCountry, storeState=storeState, storeCity=storeCity)
I would like to handle cases where users only submit one or two fields.
For e.g
1. if users only submit store name, then I should be able to return all the nodes with that store name.
2. If users only submit store name and country. Return all the stores nodes in that country
3. If users only submit store name, country and state. Return all the stores nodes in that country and state
Is it possible to write a generic cypher query to handle such scenarios i.e ignore cases where field is not set or is None or I need to write different queries to handle each case ?

SSRS: Adding a filter that returns information from entire group

I am trying to create a report in SSRS. Below is a small example of what my dataset looks like.
Example Data Set
So, there are three different stores (A,B,C) and each has a landlord (a,b,c). Landlords can pay via three different methods (1,2,3) and the amounts paid per method are shown.
Right now, I have two filters set up. The first is by Store and the second is by Landlord.
What I am having trouble with is:
How can I set up a filter by the Amount that will return information from an entire Store/Landlord?
So for example, if I wanted to filter Amount by 150, I would like to return all the "payment" information for the store(s) that have a payment of 150. Such as the following:
Desired Result
Is it possible to add a filter to return information from the entire group? (Store and Landlord are the group in this case)
I am new to SSRS so any help/insight would be greatly appreciated!
You can use LookUpSet to locate the matching groups, JOIN to put the results in a string and the INSTR function to filter your results.
=IIF(ISNOTHING(Parameters!AMOUNT.Value) OR INSTR(
Join(LOOKUPSET(Fields!Amount.Value, Fields!Amount.Value, Fields!Store.Value, "DataSet1"), ", ") ,
Fields!Store.Value
) > 0, 1, 0)
This translates to:
If the Store value is found (INSTR > 0) in the list (JOIN) of Stores where the Amount is the current Amount (Lookupset).
In your filter, put the above expression in the Expression, change the type to INTEGER and the Value to 1.
[

How to get areas/regions for a country and cities for this area/region?

We made a simple query which gets some cities:
SELECT * FROM `allCountries` WHERE name='Moscow' and `country_code` = 'RU'
Here is the result of this query:
For example, for another city we get a result with 4-7 rows.
How to get all areas/regions for a country and then get all cities for this area/region?
P.S.: Please be careful. We are not interested in an API site and database fetch. Thanks!
Background
In Geonames you have feature_classes and feature_codes which discriminate the location type. You can find detailed description of the code in the Geonames website. As in your snapshot, P.PPLC means "City (populated place) which is capital of a political entity" and S.HLC means "building (spot) hotel".
Also, every geoname have properties to identify the location in the "hierarchy" inside a country; this properties are country_code, admin1_code, admin2_code, admin3_code, admin4_code. Note that not all properties are used for every given geoname, since this depends on the political organization of a country.
Find all city inside an administrative level
To find all city inside an area (i.e. administrative level), you must first search the geoname for that admin level, in order to have the admin codes useful to filter the city query.
To find an admin level, you must first execute a query like:
SELECT *
FROM `allCountries`
WHERE `country_code` = 'RU'
AND `feature_class`='A'
AND `feature_code`='ADM1'
Note that the query filter out only the first admin levels (feature_code='ADM1'), but you can find admin level of any depth by changing it to:
SELECT *
FROM `geonames`
WHERE `country_code` = 'RU'
AND `feature_class`='A'
AND `feature_code` LIKE 'ADM_'
Now, select one record from this result set and you it to search for the cities, by using the "hierarchy" codes of that level. You should use something like (mutatis mutandis):
SELECT *
FROM `geonames`
WHERE `country_code` = "RU"
AND `feature_class`='P'
AND `feature_code` LIKE 'PPL%'
AND `admin1_code`="<admin1>"
AND `admin2_code`="<admin2>"
AND `admin3_code`="<admin3>"
AND `admin4_code`="<admin4>"
Beware of NULL admin codes, which you need to strip out from the SQL (the whole "AND ..." clause).
Of course, you can do the original "Moscow" search inside this filtered set.
The answer for your question is pretty long, but this code snippet may help you a little bit. These queries obtain all hierarchy information about given geonameid (it's plpython inside postgres).
get_geoname = plpy.prepare("SELECT geonameid, asciiname, country, admin1, admin2 FROM all_countries where geonameid=$1",
["integer"])
get_country_name = plpy.prepare("SELECT name as country from country_info where code = upper($1)", ["varchar"])
get_admin1 = plpy.prepare("SELECT asciiname, name FROM admin1 where code = $1", ["text"])
get_admin2 = plpy.prepare("SELECT asciiname, name FROM admin2 where code = $1", ["text"])

how to get a random set of records from an index with cypher query

what's the syntax to get random records from a specific node_auto_index using cypher?
I suppose there is this example
START x=node:node_auto_index("uname:*") RETURN x SKIP somerandomNumber LIMIT 10;
Is there a better way that won't return a contiguous set?
there is no feature similar to SQL's Random() in neo4j.
you must either declare the random number in the SKIP random section before you use cypher (in case you are not querying directly from console and you use any upper language with neo4j)
- this will give a random section of nodes continuously in a row
or you must retrieve all the nodes and than make your own random in your upper language across these nodes - this will give you a random set of ndoes.
or, to make a pseudorandom function in cypher, we can try smthing like this:
START x=node:node_auto_index("uname:*")
WITH x, length(x.uname) as len
WHERE Id(x)+len % 3 = 0
RETURN x LIMIT 10
or make a sophisticated WHERE part in this query based upon the total number of uname nodes, or the ordinary ascii value of uname param, for example

Can Neo4j be effectively used to show a collection of nodes in a sortable and filterable table?

I realise this may not be ideal usage, but apart from all the graphy goodness of Neo4j, I'd like to show a collection of nodes, say, People, in a tabular format that has indexed properties for sorting and filtering
I'm guessing the Type of a node can be stored as a Link, say Bob -> type -> Person, which would allow us to retrieve all People
Are the following possible to do efficiently (indexed?) and in a scalable manner?
Retrieve all People nodes and display all of their names, ages, cities of birth, etc (NOTE: some of this data will be properties, some Links to other nodes (which could be denormalised as properties for table display's and simplicity's sake)
Show me all People sorted by Age
Show me all People with Age < 30
Also a quick how to do the above (or a link to some place in the docs describing how) would be lovely
Thanks very much!
Oh and if the above isn't a good idea, please suggest a storage solution which allows both graph-like retrieval and relational-like retrieval
if you want to operate on these person nodes, you can put them into an index (default is Lucene) and then retrieve and sort the nodes using Lucene (see for instance How do I sort Lucene results by field value using a HitCollector? on how to do a custom sort in java). This will get you for instance People sorted by Age etc. The code in Neo4j could look like
Transaction tx = neo4j.beginTx();
idxManager = neo4j.index()
personIndex = idxManager.forNodes('persons')
personIndex.add(meNode,'name',meNode.getProperty('name'))
personIndex.add(youNode,'name',youNode.getProperty('name'))
tx.success()
tx.finish()
'*** Prepare a custom Lucene query context with Neo4j API ***'
query = new QueryContext( 'name:*' ).sort( new Sort(new SortField( 'name',SortField.STRING, true ) ) )
results = personIndex.query( query )
For combining index lookups and graph traversals, Cypher is a good choice, e.g.
START people = node:people_index(name="E*") MATCH people-[r]->() return people.name, r.age order by r.age asc
in order to return data on both the node and the relationships.
Sure, that's easily possible with the Neo4j query language Cypher.
For example:
start cat=node:Types(name='Person')
match cat<-[:IS_A]-person-[born:BORN]->city
where person.age > 30
return person.name, person.age, born.date, city.name
order by person.age asc
limit 10
You can experiment with it in our cypher console.

Resources