Core Data Not Equal Predicate - ios

name <> myname
I feel a bit stupid asking this question, but I am using the predicate above in a subquery. I was expecting to see all rows where name was not equal to my name. However, rows that have a NULL value for name are not being returned. Is this correct behavior?

Yes, that is to be expected. See Null Values in the "Predicate Programming Guide":
A comparison predicate does not match any value with null except null
(nil) or the NSNull null value (that is, ($value == nil) returns YES
if $value is nil).
...
If you want to match null values, you must include a specific test in addition to other comparisons, ...
That means that both "name = myname" and "name <> myname" evaluate to NO if name
is NULL.
You can change your predicate to
name <> myname OR name = NULL
to cover both cases.

Related

Neo4J Cypher - Find integer attributes

Background
I have nodes which have been recording a specific attribute as LONG and I want them to be recorded as INT - I have amended my system's input code to now record them as INT, however I am looking to check Neo4J for anomalies.
The Data
I now have a mix of data, where some have been created as "int" some as STR and some are even null (which is ok in my data-structure)
CREATE (n:logs{value: "example", records: "30"})
, (n:logs{value: "example", records: 30})
, (n:logs{value: "example", records: null})
RETURN n
The Problem
I tried to verify if the system is now writing the "records" attribute as INT rather than string, so I tried the following query;
WITH datetime("2021-06-18T06:00:00").epochMillis AS threshold
MATCH(n:logs)
WHERE n.records <> tointeger(n.records)
COUNT(n)
This returns 1 - my NULL record, for some reason. But NOT the STR, as I would have expected.
I then try the following (18th June being the date of the update to my input system);
WITH datetime("2021-06-18T06:00:00").epochMillis AS threshold
MATCH(n:logs)
WHERE n.records = tointeger(n.records)
COUNT(n)
And this returns 0 - which again, I am not sure why.
So my question is, what am I doing wrong and how can I get to where I need to go. Which is ultimately to;
Check the system is saving as INT going forwards
Change all the pre-existing records from STR to INT.
I assume for #2 is will be something like
MATCH(n:logs)
WHERE n.records <> tointeger(n.records)
SET n.records = tointeger(n.records)
Additional Info
Community edition
Version X.x.x
No addins
Your query to update to integer is correct.
To clarify your assumptions, please run below queries in your neo4j desktop or browser and you will see what is going on.
1. RETURN toInteger("2021-06-18T06:00:00")
2. RETURN toInteger(null)
Both of them will return NULL. It means your claim below is NOT true
This returns 1 - my NULL record, for some reason. But NOT the
STR, as I would have expected.
You did return 1 but is it the string value of records ('30') rather than the NULL value.
Then when you run your query below
WHERE n.records = tointeger(n.records)
And this returns 0 - which again, I am not sure why.
It is because the integer value of a string date type is also NULL. Thus it will return no matching record.
If you want to count all nodes with non-integer attribute, including nulls then you can run below query.
MATCH(n:logs)
WHERE n.records <> tointeger(n.records) OR n.records is null
RETURN count(distinct n) as cnt
Result: 2
Remember, if n.records = "2021-06-18T06:00:00" then you need to convert it to an epoch value (the integer value of time in seconds or millis since 1/1/1970). If not, then tointeger(n.records) is null and will not match in your query.
Do something like below:
MATCH (n:logs)
WHERE tointeger(n.records) is null
SET n.records = datetime(n.records).epochMillis
RETURN n
Then do your original query (this is correct!), to clean up other non-integer values.
MATCH(n:logs)
WHERE n.records <> tointeger(n.records)
SET n.records = tointeger(n.records)

Swift - iOS NSPredicate with optional NSDecimalNumber

I'm trying to use the following NSPredicate with an NSDecimalNumber to check if a value is greater than 0.
let addPredicate:NSPredicate = NSPredicate(format:"balance > 0", argumentArray: [])
"balance" is an Optional NSDecimalNumber attribute in a Core Data entity. The result is coming up empty (no errors), even when I try balance < 0, or balance == 0. I can confirm that there are no null balance records. I suspect it is due to the "optional" nature of the attribute. Predicates comparing optional dates and NSNumber values are working with no problems.
Is there a different syntax I should be using to compare an Optional NSDecimalNumber?
The fact that it is optional should not make a difference.
There is a different syntax you can use but yours should work too.
You can try the object syntax:
NSPredicate(format:"balance > %#", argumentArray: [NSDecimalNumber.zero])
But it does exactly the same as your predicate and should return the same result.
If you tried all the options i.e. grater than 0 and lower than zero and equal to zero (the equal to zero should also return entities with nil balance!), then the most simple explanation that there are no objects at all.
I don't think that the predicate is the problem, I would suggest you to check if there is some problem creating/saving new entities or maybe they are deleted ...
Hope it helps.
Have just realised the issue was that I was attempting to use a transient attribute ("balance") in the fetch predicate. So instead I have used a filter on the fetched results and this gives the correct output.
filteredItems = (fetchedResultsController.fetchedObjects?.filter { item in
let searchResult:Bool = (item.balance!.compare(NSDecimalNumber.zero) == .orderedDescending)
return searchResult
})!

SQL in AR searching if an element is not within a column array

date = Date.today
Subscription.joins(:cart).where("'#{date.beginning_of_week(:sunday).to_s}' != ANY (carts.skipped_weeks)")
The column skipped_weeks on Cart is an array of dates like ["2017-04-10", "2017-04-17"]
I am running the above query and still receiving and records that have a date included on the cart.skipped_weeks column array, I only want records that do not include that date in the skipped_weeks array.
PostgreSQL supports all as well as any:
9.23.4. ALL (array)
expression operator ALL (array expression)
The right-hand side is a parenthesized expression, which must yield an array value. The left-hand expression is evaluated and compared to each element of the array using the given operator, which must yield a Boolean result. The result of ALL is "true" if all comparisons yield true (including the case where the array has zero elements). The result is "false" if any false result is found.
Saying:
where('? != all(carts.skilled_weeks)', date.beginning_of_week(:sunday))
would probably be a more readable match for your intended logic.
Subscription.joins(:cart).where("NOT '#{date.beginning_of_week(:sunday).to_s}' = ANY (carts.skipped_weeks)")
Here is the correct form

Linq a.Metadata.ToLower().Contains

I have a problem with List of objects, which one have field for example Metadata, which is null. So when i use a.Metadata.ToLower().Contains(someText)
It shows me error, about null value. How Can I fix it ?
P.S. I see this problem first time, I tried to do the same with other List of objects which one also have null fields and it works, where can be problem ?
instead of
.Where(a => a.Metadata.ToLower().Contains(someText))
do
.Where(a => a.Metadata != null && a.Metadata.ToLower().Contains(someText))
Linq don't like null value but sometime we can't like exemple above just ignore what is null so i took habitude to cast null into the empty or minimal value.
so the value even null are cared like all other value .
have you tried a null fusion opérator in your linq query?
its : ?? operator
it will return rigth part if your data is null (in my case i return a string empty).
exemple i want sort a machine list that have some null string.
ListControleMachine.Sort((a1, a2) => (a1.MachineName ?? string.Empty).CompareTo(a2.MachineName ?? string.Empty));
you see when i sort my machine if its name is null i transform null into String.empty

core data subquery

I have an an entity containing two optional to-many relationships (childA <<-> parent <->> childB). Each of these two child entities contain an optional string that I am interested in querying on.
Using the same format, I get the results I expect for one, but not the other. I understand that means I don't understand the tools I'm working with; and hoped for some insight. This is what the two queries look like:
childA.#count != 0 AND (0 == SUBQUERY(childA, $a, $a.string != NIL).#count)
childB.#count != 0 AND (0 == SUBQUERY(childB, $a, $a.string != NIL).#count)
I would expect to get back results from non-nil instances of both childA and childB only if each entity instances' string is also nil. My question is, why would one give the results that I expect; while the other does not?
Clarification:
I'm trying to solve the general problem where I'm searching for one of two things. I'm either searching for a default value in an attribute. When the attribute is optional, I'm additionally searching for a nil attribute. The problem is further compounded when optional relationships' should only be considered when the are populated. Without the relationship count != 0, I get back all parents with a nil relationship. In one case, this is the desired behavior. In another case, this appears to diminish the returned parent count (to 0 results).
For the optional attribute case, the query might look like:
parent.#count != 0 AND (parent.gender == -1) OR (parent.gender == NIL)
Where there are optional relationships in the key-paths, the query takes the form exemplified in the first example.
Again, I have gotten the results I have expected with all but one case, where there doesn't seem to be anything unique to it's relationships nor attribute characteristics. Or I should say, there's nothing unique about this exception in data model structure or query format...
Maybe you mixed up == and != in the second clause, and it should be
childA.#count != 0 AND (SUBQUERY(childA, $a, $a.string != NIL).#count != 0)
It would be clearer what you want to achieve if you could formulate the query in plain English first.
BTW, you can use expressionForSubquery:usingIteratorVariable:predicate: of class NSExpression to build the subquery for you. You might get useful error reporting more easily then.
I understand the problem now.
In my case, it's usually logical correct to first filter out NSSets with 0 count. But, in the problematic case, it's logically correct to return the results of both NSSets with 0 count, and NSSets with > 0 count where the attribute is nil (when optional), or the attribute is set to its default value. In other words, in the problematic case, the left condition needs to be removed, resulting in the following format:
(0 == SUBQUERY(childA, $a, $a.string != NIL).#count)
It seems I'll need to have the managed objects indicate which scenario is appropriate on a case by case basis...yuk!

Resources