How i Use two contains in datastore query - google-app-engine

How i use two .contains in single query in Google Datastore.
my code:
Query query = pm.newQuery("SELECT DISTINCT actualUserEmail FROM packageName :p.contains(actualUserEmail) && :p.contains(OrgUnitPath)");
result = (List) query.executeWithArray(Arrays.asList(data),Arrays.asList(test));
System.out.println("result ="+result.size());
List tempResult = new ArrayList();
tempResult.addAll(result);
return tempResult;
i'm getting only first contains result. How i use two contains in single query.

JDO with App engine Datastore behave very unpredictable. Appengine Datastore API, is better alternate.
Here is a TESTED & TRUSTED way of having multiple contains(or IN operator) in a datastore query. Instead of JDO, I did it using google appengine datastore api:
Sample would look like:
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Filter property1Filter = new FilterPredicate("property1", FilterOperator.EQUAL, value1);
Filter property2Filter =new FilterPredicate("property2", FilterOperator.IN, valueList1);
Filter property3Filter =new FilterPredicate("property3", FilterOperator.IN, valueList2);
Filter compositeFilter= CompositeFilterOperator.and(property1Filter, property2Filter);
compositeFilterExtended=CompositeFilterOperator.and(compositeFilter, property3Filter);
com.google.appengine.api.datastore.Query gaeQuery = new Query("DatastoreKind").setFilter(compositeFilterExtended);
PreparedQuery pq = datastore.prepare(gaeQuery);
List<Entity> entities = pq.asList(FetchOptions.Builder.withDefaults());
return entities;
Hope this helps.

I got answer i made one change p & p1 in query working fine.
Query query = pm.newQuery("SELECT DISTINCT actualUserEmail FROM packageName :p.contains(actualUserEmail) && :p1.contains(OrgUnitPath)");
result = (List) query.executeWithArray(Arrays.asList(data),Arrays.asList(test));
System.out.println("result ="+result.size());
List tempResult = new ArrayList();
tempResult.addAll(result);
return tempResult;

Related

Spring+Cassandra+Solr Grouping

Is it possible to grouping data more than one field by using SolrTemplate
example, i want to group by id and name in a table
As the group options returns a list of group by fields you can probably do something like this:
Query query = new SimpleQuery(new SimpleStringCriteria("*:*"));
SimpleQuery groupQuery = new SimpleQuery(new SimpleStringCriteria("*:*"));
GroupOptions groupOptions = new GroupOptions()
.addGroupByField("id")
.addGroupByField("name")
.addGroupByQuery(query);
groupQuery.setGroupOptions(groupOptions);
GroupPage<Foo> page = solrTemplate.queryForGroupPage(query, Foo.class);
Read more in the docs here.

Row level access for google appengine datastore queries

I'm trying to develop row level access on google appengine datastore tables. So far I do have got a working example for regular ndb put(), get() and delete() operations using _hooks.
The class Acl shall be used by all the other tables. It's used as a structured property.
class Acl(EndpointsModel):
UNAUTHORIZED_ERROR = 'Invalid token.'
FORBIDDEN_ERROR = 'Permission denied.'
public = ndb.BooleanProperty()
readers = ndb.UserProperty(repeated=True)
writers = ndb.UserProperty(repeated=True)
owners = ndb.UserProperty(repeated=True)
#classmethod
def require_user(cls):
current_user = endpoints.get_current_user()
if current_user is None:
raise endpoints.UnauthorizedException(cls.UNAUTHORIZED_ERROR)
return current_user
#classmethod
def require_reader(cls, record):
if not record:
raise endpoints.NotFoundException(record.NOT_FOUND_ERROR)
current_user = cls.require_user()
if record.acl.public is not True or current_user not in record.acl.readers:
raise endpoints.ForbiddenException(cls.FORBIDDEN_ERROR)
I do want to protect access to the Location class. So I did add three hooks (_post_get_hook, _pre_put_hook and _pre_delete_hook) to the class.
class Location(EndpointsModel):
QUERY_FIELDS = ('state', 'limit', 'order', 'pageToken')
NOT_FOUND_ERROR = 'Location not found.'
description = ndb.TextProperty()
address = ndb.StringProperty()
acl = ndb.StructuredProperty(Acl)
#classmethod
def _post_get_hook(cls, key, future):
location = future.get_result()
Acl.require_reader(location)
def _pre_put_hook(self):
if self.key.id() is None:
current_user = Acl.require_user()
self.acl = Acl()
self.acl.readers.append(current_user)
self.acl.writers.append(current_user)
self.acl.owners.append(current_user)
else:
location = self.key.get()
Acl.require_writer(location)
This does work for all the create, read, update and delete operations, but it does not work for query.
#Location.query_method(user_required=True,
path='location', http_method='GET', name='location.query')
def location_query(self, query):
"""
Queries locations
"""
current_user = Acl.require_user()
query = query.filter(ndb.OR(Location.acl.readers == current_user, Location.acl.public == True))
return query
When I run a query against all locations I get the following error message:
BadArgumentError: _MultiQuery with cursors requires __key__ order
Now I've got some questions:
How do I fix the _MultiQuery issue?
Once fixed: Does this Acl implementation make sense? Are there out of the box alternatives? (I wanted to store the Acl on the record itself to be able to run a direct query, without having to get the keys first.)
Datastore doesn't support OR filters natively. Instead what NDB is doing behind the scenes is running two queries:
query.filter(Location.acl.readers == current_user)
query.filter(Location.acl.public == True)
It then merges the results of these two queries into a single result set. In order to properly merge results (in particular to eliminate duplicates when you have repeated properties), the query needs to be ordered by the key when continuing the query from an arbitrary position (using cursors).
In order to run the query successfully, you need to append a key order to the query before running it:
def location_query(self, query):
"""
Queries locations
"""
current_user = Acl.require_user()
query = query.filter(ndb.OR(Location.acl.readers == current_user,
Location.acl.public == True)
).order(Location.key)
return query
Unfortunately, your ACL implementation will not work for queries. In particular, _post_get_hook is not called for query results. There is a bug filed on the issue tracker about this.

Non-root entity group queries returning zero results

I am porting an app from Google App Engine to AppScale, and have discovered peculiar behaviour when performing ancestor queries on entity groups.
If I perform an ancestor query where the parent is not the root, the query returns zero results. If I perform the same query with the parent as root, the correct results are returned.
Easiest to illustrate with an example:
class A(ndb.Model):
name = ndb.StringProperty()
class B(ndb.Model):
name = ndb.StringProperty()
class C(ndb.Model):
name = ndb.StringProperty()
active = ndb.BooleanProperty()
sort = ndb.IntegerProperty()
def main():
a = A(name='I am A')
a.put()
b = B(parent=a.key,
name='I am B')
b.put()
C(parent=b.key,
name='I am C1',
active=True,
sort=0).put()
C(parent=b.key,
name='I am C2',
active=True,
sort=1).put()
C(parent=b.key,
name='I am C3',
active=True,
sort=2).put()
query1 = C.query(C.active == True, ancestor=a.key).order(C.sort).fetch(10)
query2 = C.query(C.active == True, ancestor=b.key).order(C.sort).fetch(10)
print 'query 1 = %s' % len(query1)
print 'query 2 = %s' % len(query2)
If I run the above code on App Engine I get 3 results for both queries. If I run it on AppScale, then I only get 3 results for the first query, and 0 results for the second query.
AppScale uses Cassandra as the datastore. Is this a subtle difference in behaviour between the App Engine datastore and Cassandra?
This is a bug in AppScale where we used the full path of the provided ancestor and not just its root entity for composite queries. The fix for it can be found here:
https://github.com/AppScale/appscale/pull/1633

Salesforce SOQL describe table

Is there a way to fetch a list of all fields in a table in Salesforce? DESCRIBE myTable doesn't work, and SELECT * FROM myTable doesn't work.
From within Apex, you can get this by running the following Apex code snippet. If your table/object is named MyObject__c, then this will give you a Set of the API names of all fields on that object that you have access to (this is important --- even as a System Administrator, if certain fields on your table/object are not visible through Field Level Security to you, they will not show up here):
// Get a map of all fields available to you on the MyObject__c table/object
// keyed by the API name of each field
Map<String,Schema.SObjectField> myObjectFields
= MyObject__c.SObjectType.getDescribe().fields.getMap();
// Get a Set of the field names
Set<String> myObjectFieldAPINames = myObjectFields.keyset();
// Print out the names to the debug log
String allFields = 'ALL ACCESSIBLE FIELDS on MyObject__c:\n\n';
for (String s : myObjectFieldAPINames) {
allFields += s + '\n';
}
System.debug(allFields);
To finish this off, and achieve SELECT * FROM MYTABLE functionality, you would need to construct a dynamic SOQL query using these fields:
List<String> fieldsList = new List<String>(myObjectFieldAPINames);
String query = 'SELECT ';
// Add in all but the last field, comma-separated
for (Integer i = 0; i < fieldsList.size()-1; i++) {
query += fieldsList + ',';
}
// Add in the final field
query += fieldsList[fieldsList.size()-1];
// Complete the query
query += ' FROM MyCustomObject__c';
// Perform the query (perform the SELECT *)
List<SObject> results = Database.query(query);
the describeSObject API call returns all the metadata about a given object/table including its fields. Its available in the SOAP, REST & Apex APIs.
Try using Schema.FieldSet
Schema.DescribeSObjectResult d = Account.sObjectType.getDescribe();
Map<String, Schema.FieldSet> FsMap = d.fieldSets.getMap();
complete documentation
Have you tried DESC myTable?
For me it works fine, it's also in the underlying tips in italic. Look:

How to separate the corresponding column value in the scriptdb query statement in google apps script

While I'm retrieving the values from the scriptdb it returns the entire db while using the below coding.
var db = ScriptDb.getMyDb();
var result = db.query({});
While using the following coding it retrieves the corresponding row fully which satisfies the condition.
var db = ScriptDb.getMyDb();
var result = db.query({p_cost:324});
I want to get the specified column value in the specified row which I retrieved already by using the above coding. Is there any possibility to get the specified column value from the scriptdb? We are write the query in traditional database as follows.
SELECE <COL_NAME> FROM <TABLE_NAME>
Try this:
while(result.hasnext()){
res = result.next();
var p_cost = res.p_cost;
}

Resources