I have a user Object, Which has inner Object of type Address. Below are the structures of both User and Address.
User{
String name;
String id;
String phoneNumber;
List<Address> address
}
Address{
String type;
String streetName;
String houseNumber;
String Country;
int pin
}
I am storing the User Objects to the Hazelcast Cache. I would like to query Users whose address type is "Primary" and Country is "US".
The problem I am seeing is that each user can have multiple addresses, How to loop through the address and find the one with type "Primary" and for that particular address type how to query the Country "US". Can we use predicate to achieve this? If so, Please help me with how the predicate can be constructed.
Please check Querying in Collections and Arrays in the Hazelcast documentation.
In your case, you would like to have two conditions on the dependent collection, like:
Predicates.equal("address[any].country", "US")
Predicates.equal("address[any].type", "Primary")
But any should apply to the same entity (because you'd like to have US as Primary country). I don't think you can achieve it with just Predicates.
What you can do, however, is to use Custom Attributes and define your own ValueExtractor which would cover the logic you need.
Related
i have an object "ResponseSerializablePlus"
the object has a few attributes
private int id;
private String cod_nrbe_en;
private int num_sec_ac
this field can bring null values so i need to capture all the registers about this field, you can have id or another field duplicated more than once.
what i was thinking was building a query
Predicate sqlQuery = Predicates.sql("i dont know what to put here");
Predicate criteriaQuery = Predicates.and(
Predicates.equal("id", id),
Predicates.equal("code", cod_nrbe_en)
Predicates.equal("num", num_sec_ac)
);
you can have just 1 value and other fields are null or another case the thing is i dont know how to query or compare those 3 attributes
¿any hint?
I am trying to replicate the following type of SQL query that you can perform in SQL Server...the important part here is the WHERE clause:
Select InventoryCD from InventoryItem WHERE InventoryCD IN ('123123', '154677', '445899', '998766')
It works perfectly using the IN3<> operator and a series of string constants:
i.e. And<InventoryItem.inventoryCD, In3<constantA,constantB,constantC>,
However, I need to be able to do this with an arbitrarily long list of values in an array, and I need to be able to set the values dynamically at runtime.
I'm not sure what type I need to pass in to the IN<> statement in my PXProjection query. I have been playing around with the following approach, but this throws a compiler error.
public class SOSiteStatusFilterExt : PXCacheExtension<SOSiteStatusFilter>
{
public static bool IsActive()
{
return true;
}
public abstract class searchitemsarray : PX.Data.IBqlField
{
}
[PXUnboundDefault()]
public virtual string[] Searchitemsarray { get; set; }
}
I think maybe I need an array of PXString objects? I'm really not sure, and there isn't any documentation that is helpful. Can anyone help?
This shows how to do it with a regular PXSelect: https://asiablog.acumatica.com/2017/11/sql-in-operator-in-bql.html
But I need to be able to pass in the correct type using Select2...
For reference I will post here the example mentioned by Hugues in the comments.
If you need to generate a query with an arbitrary list of values generated at runtime like this:
Select * from InventoryItem InventoryItem
Where InventoryItem.InventoryCD IN ('123123', '154677', '445899', '998766')
Order by InventoryItem.InventoryCD
You would write something like this:
Object[] values = new String[] { "123123", "154677", "445899", "998766" };
InventoryItem item = PXSelect<InventoryItem,
Where<InventoryItem.inventoryCD,
In<Required<InventoryItem.inventoryCD>>>>.Select(Base, values);
Please note that In<> operator is available only with Required<> parameter and you need to pass array of possible values manually to Select(…) method parameters. So you need to fill this array with your list before calling the Select method.
Also, the Required<> parameter should be used only in the BQL statements that are directly executed in the application code. The data views that are queried from the UI will not work if they contain Required<> parameters.
I ended up creating 100 variables and using the BQL OR operator, i.e.
And2<Where<InventoryItem.inventoryCD, Equal<CurrentValue<SOSiteStatusFilterExt.Pagefilter1>>,
Or<InventoryItem.inventoryCD, Equal<CurrentValue<SOSiteStatusFilterExt.Pagefilter2>>,
Or<InventoryItem.inventoryCD, Equal<CurrentValue<SOSiteStatusFilterExt.Pagefilter3>>,
Or<InventoryItem.inventoryCD, Equal<CurrentValue<SOSiteStatusFilterExt.Pagefilter4>>,
etc...etc...
You can then set the value of Pagefilter1, 2, etc inside of the FieldSelecting event for SOSiteStatusFilter.inventory, as an example. The key insight here, which isn't that obvious to the uninitiated in Acumatica, is that all variables parameterized in SQL Server via BQL are nullable. If the variable is null when the query is run, SQL Server automatically disables that variable using a "bit flipping" approach to disable that variable in the SQL procedure call. In normal T-SQL, this would throw an error. But Acumatica's framework handles the case of a NULL field equality by disabling that variable inside the SQL procedure before the equality is evaluated.
Performance with this approach was very good, especially because we are querying on an indexed key field (InventoryCD isn't technically the primary key but it is basically a close second).
Given that one can't subclass builtin types in Kotlin, I'm looking for a way to add special method functionality to specific types of string fields in a record, without applying those extension functions to all strings (even within that record type). Say, for example, I have some mutable string fields inside a record, for which I want to define special purpose behaviors.
class Customer {
// ...
var zipcode: String
var email: String
// ...
}
For zipcode, assume I'd like to be able to call
thisCustomer.zipcode.plusFour to get the +4 of the zip code (99999-9999) via regex.
For email, assume I'd like to be able to call
thisCustomer.email.domain to have a regex go get the ...#company.com
portion of the specified email.
My objectives are to:
Avoid the runtime overhead of boxing zipcode into a class Zipcode with just a
single var inside, given that the size of the Customer recordset could potentailly be millions.
Avoid the syntax of having to assign
thisCustomer.zipcode.value = "99999-9999" or thisCustomer.zipcode = Zipcode("99999-9999"), if I did end up having to box the string.
Avoid adding general String.plusFour and
String.domain extension properties, even just within the Customer
class... because zipcodes and emails could technically call each others'
extensions
I've been thinking this over and considered the following options, but struck out with each:
subclassing String: Not possible since strings (and all built-ins)
are closed
applying an interface Zip to the var declaration (var zipcode:
String, Zip): No such syntax I could find
adding inner functions within the getter itself: Syntax doesn't seem to exist for this
using objects or functions-within-functions: Couldn't think of a way
for this to work, although I might not be imaginative enough
Am I missing an obvious solution here? Even if not obvious, with all the syntactic magic of Kotlin, is there a way to make it happen? Maybe there's a way to accomplish some/all of the objectives above without using any of these approaches?
You can use type aliases to make the intention clear:
typealias ZipCode = String
val ZipCode.plusFour get() = ...
typealias Email = String
val Email.domain get() = ...
class Customer {
// ...
var zipcode: ZipCode
var email: Email
// ...
}
Unfortunately, this only clarifies intentions and doesn't stop the compiler from allowing zipcode.domain. But for now I don't think there is any way which satisfies both objectives 1 and 3.
Kotlin developers have decided not to support assignment-incompatible type aliases, which would have fit all your requirements, in favor of waiting for value classes to be available on JVM, as discussed in https://github.com/Kotlin/KEEP/issues/4.
You may create a decorator class using delegate:
class YourString(val value: String) : Comparable<String> by value, CharSequence by value {
val plusFour: String
get() = "" //your logic here
val domain: String
get() = "" //your logic here
override fun toString() = value
}
Usage:
fun String.toYourString() = YourString(this)
class Customer(var zipCode: YourString, var email: YourString)
val customer = Customer("+4 99999-9999".toYourString(), "xxx#company.com".toYourString())
println(customer.zipCode.plusFour)
println(customer.email.domain)
The data being returned from a stored procedure has 3 columns of repeating data:
Name | Address | PhoneNumber | UniqueCol1 | UniqueCol2
Ideally I want my model to show that there is repeated data by only storing the values once and have a collection of the unique data.
public class MyViewModel
{
public string Name {get;set;}
public string Address {get;set;}
public string PhoneNumber {get;set;}
public List<MyModel> UniqueData {get;set;}
public class MyModel
{
public string UniqueCol1 {get;set;}
public string UniqueCol2 {get;set;}
}
}
This means I want to map a collection of results to a single object of MyViewModel:
return Mapper.Map<List<StoredProcedureObject>, MyViewModel>(result);
This is where I get my error as I assume I have some configuration that I need to do:
Mapping types:
List`1 -> MyViewModel
Any ideas on the missing step to get this to work?
Automapper is only able to flatten your structure into something simpler. But it's not possible to map a simple class to something more specific.
I would suggest to take only the first entry in your table to fill your base fields like Name, Address, PhoneNumber and iterate over your results to fill your UniqueData List.
I don't see an easier way, because with each possible mapping and without using seperate loops you will get your base data multiple times.
If you don't mind to use another tool, maybe you will have a look at ValueInjecter. I heard you can use this tool for two-way-mappings.
I am inserting data into my entity table using .AddObject(). The object is of the entity table's type. The object is eventStudent, it has string eventStudent.ID, bool eventStudent.StudentPresent, bool eventStudent.ParentPresent.
The students are a list of strings containing student ids. Their presence at the event is in another object called attendees, consisting of String studentID, bool studentPresent and bool parentPresent. Only student id's that have true for StudentPresent and/or ParentPresent are in the attendees list.
As I load up my eventStudent object, I need to set StudentPresent and ParentPresent. This is what I came up with:
foreach (StudentMinimum student in students)
{
eventStudent.StudentPresent = (from a in attendees
where a.StudentID.Contains(student.StudentID)
&& a.StudentPresent
select a.StudentPresent);
}
I receive the error cannot implicitly convert type 'System.Collections.Generic.IEnumerable' to 'bool'
How can I improve my query so eventStudent.StudentPresent is set to either True or False?
The compiler doesn't know what type will be returned from your query as you haven't explicitly casted it to a type. As a result, it gets a generic IEnumerable type (there could be many records returned right? Hence the IEnumerable. And those records could each be of any type, hence the generic type).
So if the data in your DB were bad and you got multiple records back, converting:
StudentPresent
true
false
false
to a bool is not going to happen. There are a few ways you could get around this. Personally, I'd do something like
var studentPresent = (from a in attendees
where a.StudentID.Contains(student.StudentID)
&& a.StudentPresent
select a.StudentPresent).FirstOrDefault();
eventStudent.StudentPresent = (bool)studentPresent;
Well, actually, I'd use a lambda query instead but that's just personal preference.