Inequality query not working ndb - google-cloud-datastore

Session.sessionType is a StringProperty(repeated=True)
When I do this query:
sessions_no_type = Session.query(Session.sessionType == request.sessionType)
everything seems to be working and I get only those sessions who have request.sessionType in them
but when I try:
sessions_no_type = Session.query(Session.sessionType != request.sessionType)
I get back all sessions (regardless of request.sessionType)
What might be the problem for this? Even docs have a similar example but it does not work for me.
The same goes when trying this version:
filter = ndb.query.FilterNode("sessionType", "!=", request.sessionType)
when tested for equality it returns everything correctly, but inequality case ONLY eliminates Session objects which have ONE sessionType which is equal to the passed(request) sessionType

The documentation for The != and IN Operations says:
The != (not-equal) and IN (membership) operations are implemented by
combining other filters using the OR operation. The first of these,
property != value
is implemented as
(property < value) OR (property > value)
Because you are using a repeated StringProperty, if any of the strings in sessionType are not equal to request.sessionType then that entity will be returned in the query.

Related

How do I handle optional query parameters for a Go using Mux properly?

I'm making an API server using GoLang and I am using Mux as the HTTP router. I have one endpoint in my app, /tasks. When I hit that endpoint, I get back an array of results, which is as expected. Now, I want to build upon that and add an optional query parameter into the URL to only return N results, like so: /tasks?num=5 which would only return 5 results. I have accomplished this using the handler below:
vars := r.URL.Query()
t := task{}
if numOfTasksParam, ok := vars["num"]; ok {
fmt.Printf("%+v", numOfTasksParam[0])
numOfTasks, err := strconv.Atoi(vars.Get("num"))
//return only n number of results
} else {
//return the entire result set
}
I devised this solution because I discovered that URL.Query() returns a map of the query parameters and therefore, I can just check to see if that map contained the key of "num". If so, the client wants N number of results. If not, the client must want the whole result set.
The main issue I have with this approach is that when I go to check if the keys exists, I make a temporary variable called numOfTasksParam which holds the query parameter value, but it holds the value as a string and I need a int. Therefore, I must use the numOfTasksParam somehow and then create another variable to convert that to an integer value.
Is there more succinct or convenient way of checking if a query parameter exists in the request URL?
This is probably the most succinct, and works because Get returns an empty string if the parameter isn't set, which Atoi will fail to parse:
vars := r.URL.Query()
t := task{}
if numOfTasks, err := strconv.Atoi(vars.Get("num")); err == nil {
//return only numOfTasks number of results
} else {
//return the entire result set
}
The price you pay for having less code is that if a user passes an invalid value like ?num=taco, it will be treated as if they passed nothing, rather than telling the user they passed something unusable. This may or may not be what you want. It is also slightly less efficient, because it will run Atoi even if the value is known to be empty.

Can't use .AddDays in EF core 3.1 query

I'm trying to migrate my project from .net core 2.2 to 3.1,the following code worked fine but now gives that error:
System.InvalidOperationException: The LINQ expression
'DbSet .Where(h =>
h.DATAI.AddDays((double)Convert.ToInt32((object)h.NRZILE)) >= __date_0
&& h.DATAI.AddDays((double)Convert.ToInt32((object)h.NRZILE)) <
__AddDays_1 || h.DATAI <= __AddDays_1 && h.DATAI.AddDays((double)Convert.ToInt32((object)h.NRZILE)) >=
__AddDays_1)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly
by inserting a call to either AsEnumerable(), AsAsyncEnumerable(),
ToList(), or ToListAsync().
public async Task<IActionResult> getOp(int day, int month, int year, int daysToShow)
{
var date = new DateTime(year, month, day);
return Ok(await db.HT_REZ
.Where(r => (r.DATAI.AddDays(Convert.ToInt32(r.NRZILE)) >= date && r.DATAI.AddDays(Convert.ToInt32(r.NRZILE)) < date.AddDays(daysToShow))
|| (r.DATAI <= date.AddDays(daysToShow) && r.DATAI.AddDays(Convert.ToInt32(r.NRZILE)) >= date.AddDays(daysToShow))
)
.Select(r => new { r.ID, .... })
.ToListAsync()
);
}
I found that implicit client evaluation has been disabled in EF Core 3 and I have to use AsEnumerable before filtering data,but was not able to fix above query
thanks for any help
The problem is not the DateTime.AddDays call, which is supported.
Note that the exception message shows the whole Where operator, so the problem (unsupported) should be in some other expression inside the predicate.
In this specific case the unsupported is the Convert.ToInt32(r.NRZILE) expression, which for NRZFILE type int? matches Convert.ToInt32(object).
While EF Core supports a subset of Convert class methods, in general you should avoid them (except conversions from string) by using C# casts or null coalescing operator.
e.g. replace all occurrences of
Convert.ToInt32(r.NRZILE)
with
(int)r.NRZILE
or (in the context of DateAdd)
r.NRZILE ?? 0
and the issue will be solved.
You need to use the DbFunctions extension methods and think of a different approach: try to calculate the difference between dates instead (DateDiffDay method). Please see https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbfunctions?view=efcore-3.1.
Also, I don't think that you can use Convert in an expression, so if the values are already numbers, just use them as such.

Java 8 Map merge VS compute, essential difference?

It seems Both merge and compute Map methods are created to reduce if("~key exists here~") when put.
My problem is: add to map a [key, value] pair when I know nothing: neither key existing in map nor it exist but has value nor value == null nor key == null.
words.forEach(word ->
map.compute(word, (w, prev) -> prev != null ? prev + 1 : 1)
);
words.forEach(word ->
map.merge(word, 1, (prev, one) -> prev + one)
);
Is the only difference 1 is moved from Bifunction to parameter?
What is better to use? Does any of merge, compute suggests key/val are existing?
And what is essential difference in use case of them?
The documentation of Map#compute(K, BiFunction) says:
Attempts to compute a mapping for the specified key and its current mapped value (or null if there is no current mapping). For example, to either create or append a String msg to a value mapping:
map.compute(key, (k, v) -> (v == null) ? msg : v.concat(msg))
(Method merge() is often simpler to use for such purposes.)
If the remapping function returns null, the mapping is removed (or remains absent if initially absent). If the remapping function itself throws an (unchecked) exception, the exception is rethrown, and the current mapping is left unchanged.
The remapping function should not modify this map during computation.
And the documentation of Map#merge(K, V, BiFunction) says:
If the specified key is not already associated with a value or is associated with null, associates it with the given non-null value. Otherwise, replaces the associated value with the results of the given remapping function, or removes if the result is null. This method may be of use when combining multiple mapped values for a key. For example, to either create or append a String msg to a value mapping:
map.merge(key, msg, String::concat)
If the remapping function returns null, the mapping is removed. If the remapping function itself throws an (unchecked) exception, the exception is rethrown, and the current mapping is left unchanged.
The remapping function should not modify this map during computation.
The important differences are:
For compute(K, BiFunction<? super K, ? super V, ? extends V>):
The BiFunction is always invoked.
The BiFunction accepts the given key and the current value, if any, as arguments and returns a new value.
Meant for taking the key and current value (if any), performing an arbitrary computation, and returning the result. The computation may be a reduction operation (i.e. merge) but it doesn't have to be.
For merge(K, V, BiFunction<? super V, ? super V, ? extends V>):
The BiFunction is invoked only if the given key is already associated with a non-null value.
The BiFunction accepts the current value and the given value as arguments and returns a new value. Unlike with compute, the BiFunction is not given the key.
Meant for taking two values and reducing them into a single value.
If the mapping function, as in your case, only depends on the current mapped value, then you can use both. But I would prefer:
compute if you can guarantee that a value for the given key exists. In this case the extra value parameter taken by the merge method is not needed.
merge if it is possible that no value for the given key exists. In this case merge has the advantage that null does NOT have to be handled by the mapping function.

Specman e: Is there a way to constrain the amount of set bits in a number?

I have unit field events:
events:uint;
The values of events not so interesting as the amount of set bits in it. I would like to constrain the ranges of the amount of set bits in the events.
Is there a way to do it?
Thank you for your help.
The operations [..] and %{} aren't generative therefore they considered as inputs in the constraints.
The constraint:
keep events_bits == events[..];
is equivalent to:
keep events_bits == read_only(events[..]);
The generator will generate events and only then will enforce the constraints on `events_bits.
You can do the following:
extend sys {
events : uint;
events_bits_on [32] : list of bool;
keep for each in events_bits_on {
it == (events[index:index] == 1);
};
keep events_bits_on.count(it) == 2;
};
There might be an easier way to do it, but you can use bit slicing to constrain a list of uints to equal the bits of your variable, and use sum to constrain their amount.
The following example does what you need (limited to a 4 bit variable for brevity):
<'
extend sys {
events : uint(bits:4);
b: list of uint(bits:1);
keep b.size() == 4;
keep b[0] == events[0:0];
keep b[1] == events[1:1];
keep b[2] == events[2:2];
keep b[3] == events[3:3];
keep (b.sum(it) == 2);
};
'>
Writing all the constraints is probably a little ugly, but it can easily be done using a define as computed macro.
This is only a partial answer.
You can use events[..] or %{events} to convert from a vector to a list containing the bits of that vector. Using it directly in a constraint directly doesn't work, because it complains there's no generative element:
extend sys {
events : uint(bits:4);
// neither of these compile
keep events[..].sum(it) == value(2);
keep %{events}.sum(it) == value(2);
};
This is probably a case for Cadence.
What is allowed however is to create an intermediate list and assign that to the output of either of these operators:
extend sys {
events_bits : list of bit;
keep events_bits == events[..];
};
You would think that you could then constrain this list to have a certain number of 1s:
extend sys {
// these constraints apply, but aren't enforced
keep events_bits.sum(it) == value(2);
keep events_bits.count(it == 1) == value(2);
};
This doesn't work however. Even though the constraints are there, they don't get enforced for some reason. This is another issue for Cadence to look at.
Summarizing, if these issues weren't there, you could probably count the number of ones easily. Maybe in a future version of Specman. I still hope that at least seeing that the [..] and the %{} operators exist will help you for other things.

Ordering using a declared variable's property

I have a ScInfo class that exists in many different classes. This class also has a list of ScDetails which has a Date member variable called nextExecution.
I need to continuously look up eligible objects with their ScDetails object's nextExecution member variable is after or equal to the current server's time (i.e. persistenceManagerInstance.getServerDate()). Meaning that I need to look up objects, with ScInfo having a ScDetails object with nextExecution >= serverDate)
So I use the following method (A portion is shown):
public List<Object[]> getEligbleForExecution(long amount) {
PersistenceManager pm = null;
Transaction t = null;
try {
pm = getPM();
t = pm.currentTransaction();
t.begin();
Query q = pm
.newQuery(
entityClass, //This is generic
"!this.deleted && this.scheduleActive && det.active == true && (det.nextExecution == null || det.nextExecution <= :serverDate) && det.running == false && this.scInfo.scDetails.contains(det)");
q.declareVariables(ScDetail.class.getName() + " det;");
q.setRange(0, amount);
q.setResult("this, det");
q.setOrdering("det.nextExecution"); // This is the statement I need to apply but it's causing the error below
Date serverDate = pm.getServerDate();
List<Object[]> raw = new ArrayList<Object[]>((List<Object[]>) q.execute(serverDate));
Which throws the following error stack trace (DEBUG level, I mentioned what I thought to be essential for solving this problem):
14:54:32 DEBUG (Log4JLogger.java:58)-[main] >> QueryToSQL.processVariable (unbound) variable=det is not yet bound so returning UnboundExpression
14:54:32 DEBUG (Log4JLogger.java:58)-[main] Updating mapping of org.datanucleus.store.rdbms.sql.expression.NullLiteral#727f3b8a to be org.datanucleus.store.mapped.mapping.DateMapping#e72a8082
14:54:32 DEBUG (Log4JLogger.java:58)-[main] Transaction rolling back for ObjectManager org.datanucleus.MultithreadedObjectManager#fba0f36
14:54:32 DEBUG (Log4JLogger.java:58)-[main] Rolling back [DataNucleus Transaction, ID=Xid={A strange uncopyable character is in here !}, enlisted resources=[]]
14:54:32 DEBUG (Log4JLogger.java:58)-[main] Transaction rolled back in 1 ms
14:54:32 ERROR (ScTasksDAOImpl.java:67)-[main] Looking up eligible SC tasks
java.lang.NullPointerException
at org.datanucleus.store.rdbms.query.QueryToSQLMapper.processVariableExpression(QueryToSQLMapper.java:3245)
at org.datanucleus.store.rdbms.query.QueryToSQLMapper.processPrimaryExpression(QueryToSQLMapper.java:2075)
at org.datanucleus.query.evaluator.AbstractExpressionEvaluator.compilePrimaryExpression(AbstractExpressionEvaluator.java:180)
at org.datanucleus.query.evaluator.AbstractExpressionEvaluator.compileUnaryExpression(AbstractExpressionEvaluator.java:169)
at org.datanucleus.query.evaluator.AbstractExpressionEvaluator.compileAdditiveMultiplicativeExpression(AbstractExpressionEvaluator.java:148)
at org.datanucleus.query.evaluator.AbstractExpressionEvaluator.compileRelationalExpression(AbstractExpressionEvaluator.java:123)
at org.datanucleus.query.evaluator.AbstractExpressionEvaluator.compileOrAndExpression(AbstractExpressionEvaluator.java:65)
at org.datanucleus.query.evaluator.AbstractExpressionEvaluator.evaluate(AbstractExpressionEvaluator.java:46)
at org.datanucleus.query.expression.Expression.evaluate(Expression.java:337)
at org.datanucleus.store.rdbms.query.QueryToSQLMapper.compileOrdering(QueryToSQLMapper.java:845)
at org.datanucleus.store.rdbms.query.QueryToSQLMapper.compile(QueryToSQLMapper.java:403)
at org.datanucleus.store.rdbms.query.JDOQLQuery.compileQueryFull(JDOQLQuery.java:883)
at org.datanucleus.store.rdbms.query.JDOQLQuery.compileInternal(JDOQLQuery.java:343)
at org.datanucleus.store.query.Query.executeQuery(Query.java:1747)
at org.datanucleus.store.query.Query.executeWithArray(Query.java:1666)
at org.datanucleus.api.jdo.JDOQuery.execute(JDOQuery.java:243)
at com.sc.ipk.sc.services.ScTasksDAOImpl.getEligbleForExecution(ScTasksDAOImpl.java:41)
at com.sc.ipk.ixl.services.IxlTestDAOImpl.main(IxlTestDAOImpl.java:977)
14:54:32 DEBUG (Log4JLogger.java:58)-[main] Object Manager "org.datanucleus.MultithreadedObjectManager#fba0f36" closed
So is it not possible to use declared variables to query ordering ? I tried using sub-queries but I couldn't get that to work either, may be I can start a new question for that, if ordering using declared variables isn't possible.
EDIT:
Neil generously suggested that ordering based on an element that should exist in a collection doesn't look reasonable to him. I understand that but I cannot for example look-up ScDetails objects first after ordering them of course and then look-up my main objects afterwards because my target main object may differ from time to time and I may look-up ScDetails objects that doesn't belong to the main candidate class.
For example:
A has ScInfo which has a collection of ScDetails
B, C (Same as above)
So if I lookup ScDetails objects first (After ordering an all), I cannot filter my main candidate classes (A, B & C) because I may use a ScDetails that belongs to A while I'm trying to get B or C candidates.
Thank you.
I don't see how you can order by that variable. It represents an element of a collection of the candidate. Consequently if a candidate has say 5 elements then it is indeterminate how it can order by some property on the element (1-N mapping). Obviously if the candidate was the element then ordering by some property of the element makes perfect sense, whether variable or not.

Resources