datastore only matches root ancestor - google-cloud-datastore

I have a structure such as this.
User -> Language -> Property: value
when I query:
select * from Property where __key__ has ancestor(User, 'me')
it returns my list of properties.
Yet when I query
select * from Property where __key__ has ancestor(Language, 'en')
Nothing is returned.
In the properties I can see that the google console UI does show the correct hierarchy. What is strange to me is that it seems to match the root parent rather than the intermediate links in the tree.
Is there something that I'm missing here?

With your second query, you are actually looking for a for a root entity with the key (Language, 'en'). To make the second query work, you want to do something like: select * from Property where __key__ has ancestor KEY(User, 'me', Language, 'en') .

Related

Datastore: `SELECT * FROM Entity WHERE property IS NULL` returns no result despite entities without property

I am using Google Cloud Datastore and successfully stored entities.
Now I am trying to query them based on the presence of a property.
I use the "Query by GQL" tab in the Datastore UI: https://console.cloud.google.com/datastore/entities/query/gql
For some entities, I did not specify the property property when I saved them, so I expect these to be set to NULL.
However, when I query SELECT * FROM Entity WHERE property IS NULL, no result is returned.
This is working as intended:
According to the Datastore documentation:
Null is a value, not the absence of a value.
There is no way to determine whether an entity lacks a value for a property (that is, whether the property has no value). If you use a condition of the form nonexistent = NULL, what will occur is a check whether a null value is explicitly stored for that property. For example, SELECT * FROM Task WHERE nonexistent = NULL will never yield an entity with no value set for property nonexistent.
So to explicitly retrieve entities with property set to NULL, you would have to store the property: NULL for these entities.
What you are trying to achieve is not possible. NULL is not the same as property not present.
But as mentioned by Nick Johnson here,
The workaround would be to provide a default value for the updated property, and query for that value
I haven't tried this personally, and I am not sure if it works, but I suggest you to try this.
If it doesn't work, the only other option is to go through every record of the model and update all the existing entities which do not have a value, with a default value.

Google Cloud datastore : Use the cursor in a reverse query

Documentation > Datastore Queries > Limitations of cursors
sort order
An exception is if the original query's final sort order was on __key__. In that case, you can use the cursor in a reverse query, which is the original query with each sort order reversed. The reverse query can modify the start cursor, end cursor, offset, and limit.
Although it is stated that only __key__ can be used in the reverse order, it seems that it is also available in another property that created custom index. I tried it both in development environment and production environment.
What mean "An exception is if the original query's final sort order was on __key__." ?
Let me clarify this with a simple example:
Let's say you have a query (omitting cursor/limit syntax) -
SELECT * FROM MyEntity ORDER BY PROP1 ASC
Now the requirement is that you need to traverse both in forward and reverse directions and using cursors.
The first thing you need to do is to modify your query to have __key__ as the last sort -
SELECT * FROM Entity ORDER BY PROP1 ASC, __key__ ASC
You can traverse forward normally using cursors, but when you need to traverse backwards, you need to execute the query by reversing the sort order. You can still use the same cursor of the page you are on. So, the query will change to
SELECT * FROM Entity ORDER BY PROP1 DESC, __key__ DESC
Notice that we have changed ASCendng order to DESCending.
This would essentially give you the previous records from the current cursor location. In order for this to work, you need to have appropriate composite indexes (for example one on PROP1 and __key__ in DESC order). Of course you can also add other properties to the sort order, or remove PROP1 from the example, if you are fine with the results sorted just by key.
With out key as the last sort, you won't be able use the cursor you got when going forward in a reverse order query. That's what that "Exception" rule is.

CMIS aspect query with path

I need to query a particular folder in the repository using a java based scheduler in alfresco.
I need to check whether the custom aspect's property is present or not.
Below query works for me when I don't use the path query.
select * from myType:caseDoc as d join myAspect:caseId as s on d.cmis:objectId = s.cmis:objectId
The problem with the above query is it searches all the contents in the repository but I want to target a particular folder.
When I try to put the CONTAINS in the above query it fails.
select * from cch:caseDoc as d
join cch:caseId as s on d.cmis:objectId = s.cmis:objectId WHERE CONTAINS('PATH:"//app:company_home/cm:FWED/cm:CDO/cm:CAB-DROP-FOLDER/*"')
It gives below exception
A selector must be specified when there are two or more selectors
Thank you
It looks like you may be missing one argument in CONTAINS(). Did you try something like this?
select *
from cch:caseDoc as d
join cch:caseId as s
on d.cmis:objectId = s.cmis:objectId
WHERE CONTAINS(d,'PATH:"//app:company_home/cm:FDLE/cm:CCH/cm:CCH-D‌​ROP-FOLDER/*"')
(I'm just putting my comment as an answer)
Well, if you are worrying about the path, then you should put
CONTAINS('PATH:"/app:company_home/cm:FWED/cm:CDO/cm:CAB-DROP-FOLDER/*"')
With one single / at the start of the path, if you which to only search in direct children to that path or :
CONTAINS('PATH:"/app:company_home/cm:FWED/cm:CDO/cm:CAB-DROP-FOLDER//*"')
to perform the lookup in the whole underlying hierarchy!
However, I do think that the query you provided and the behaviour you described does not match each other !

where clause does not work in GAE datastore viewer

I am new to GAE, please excuse for being naive.
datastore viewer query with where clause returns "No results in Empty namespace.".
For instance:
select * from GaeUser
returns all the entires.
Something like,
select * from GaeUser where firstName = 'somename'
or
select * from GaeUser where dayOfBirth = 5
returns nothing but the message No results in empty namespace.
I am expecting some pointers on how to debug this.
Thanks for reading this!!
Simply you just wrote an incorrect/misspelled query.
Note that GAE datastore is schema-less. Writing a query for a nonexisting entity or for a nonexisting property or specifying a filter condition where you use an incorrect data type will not result in error but rather in an empty result.
Being schema-less also means that 2 entities of the same kind might have the same property with different types. For example you might have a Person entity with an age property of type int and another Person with an age property of type String. Obviously in this case if you write something like
select * from Person where age='5'
will not return the person who has age=5 property having int type.
So just simply double check the names and types of the entity and properties and try again.
Another important note:
Properties are indexed by default. This means when saving an entity, index records for an indexed property will automatically be created and saved, this allows you to find this entity by this indexed property. Properties can be made unindexed. When you save an entity with an unindexed property, index records will not be saved (or if there were any, they will be removed) for this unindexed property and you will not be able to query/find this entity by this unindexed property.

A limitation of Sqlite3's full text search doesn't allow ORs with MATCHes. Workaround?

Sqlite3's full text search facility - FTS3 - allows to use MATCH operator for fast full-text search:
SELECT ItemId FROM docs WHERE docs.text MATCH 'linux'
However, it does not support OR operator anywhere in an SQL query where there's a MATCH (source: 1, 2):
SELECT ItemId FROM docs WHERE docs.text MATCH 'linux' OR column=value
error: unable to use function MATCH in the requested context
(Not to be confused with OR operator in the FTS3 query itself, i.e. SELECT ItemId FROM docs WHERE docs.text MATCH 'linux OR unix'. This works fine.)
Is there a way to rewrite the query so that it works (even if it's somewhat slower)?
Rewriting the query using temporary views will work as expected:
CREATE TEMP VIEW view1 AS SELECT ItemId FROM docs WHERE docs.text MATCH 'linux'
SELECT * FROM docs WHERE ItemId IN view1 OR column=value
DROP VIEW view1
The speed will be comparable to that of a "direct" query (without the temporary view) if the temporary view is not "sweeping", i.e. it does not generate a lot of rows.

Resources