How to achieve conditional searching via Spotlight indexing? - ios

Currently, I am porting a SQLite based app, to CoreData based app.
This is my CoreData entity
Entity Note
-----------
var type: Int
var locked: Bool
var title: String?
var searched_string: String?
var body: String?
One CoreData feature which I would like to adopt is spotlight indexing.
In the legacy SQLite based app, we are performing the following conditional searching
SELECT * FROM Note WHERE
(title LIKE :searchedStringWithPercentageSigns ESCAPE '\') OR
(type = 1 AND locked = 0 AND searched_string LIKE :searchedStringWithPercentageSigns ESCAPE '\') OR
(type = 0 AND locked = 0 AND body LIKE :searchedStringWithPercentageSigns ESCAPE '\')
ORDER BY "order" ASC
This interpreted as
First, search at property (column) title
If not, search at property searched_string, only if type is 1 and locked is 0
If not, search at property body, only if type is 0 and locked is 0
If not, do not search for anything. (locked is 1)
After watching https://developer.apple.com/videos/play/wwdc2021/10098/ , I still do not have a clear idea on how to implement such condition searching behavior
Full text search inside the app via CSSearchQuery
Search outside the app via Spotlight search
I know I need to
In Data Model Editor, I need to select Index in Spotlight for title, searched_string, body. But, do I need to do the same for properties (type, locked) which is used for condition checking?
What is the way to achieve conditional searching via Spotlight indexing?
Thanks.

Related

How to bind an entity object on a Detail page

I am developing a master detail Fiori app using SAP UI5. As the details contains more than 40 columns, I made separate OData services for master & detail.
In Master page, data are coming correctly. Now my task is that on any table line, when user clicks on Detail, next page will be open with details base on two key values of master table.
I'm getting two keys in variables in detail page as follows and it is working fine:
var spayid = jQuery.sap.getUriParameters().get("payid");
var spaydt = jQuery.sap.getUriParameters().get("paydt");
Next, I have created two filters as follows which is also working fine.
var filter1 = new Filter({
path: "Laufi",
operator: FilterOperator.EQ,
value1: spayid
});
var filter2 = new Filter({
path: "Laufd",
operator: FilterOperator.EQ,
value1: spaydt
});
Now I am calling OData service which is also working fine:
var oODataModel = new ODataModel("proxy/http/FIORI-DEV.abc.com:8000/sap/opu/odata/sap/ZASA_FI_pay_D_SRV?sap-client=100", {
json: true,
useBatch: false
});
this.getView().setModel(oODataModel);
I don't know now how to filter data. What should be included in above so that it will filter data according to my filters filer1 and filter2? I have tried following but it is not working.
filters : [ filter1, filter2 ],
json: true,
useBatch: false
I am very good in ABAP but not an expert in SAPUI5. I am in learning phase.
First of all, I was thinking to pass parameters on OData service so that only the required data are fetched. Means my OData call should be like this:
new ODataModel("proxy/http/FIORI-DEV.abc.com:8000/sap/opu/odata/sap/ZASA_FI_PAYMENT_D_SRV/PdetailSet(Laufi= spayid, Laufd = spaydt)?sap-client=100");
But this seems not like possible.
Second option is that I will fetch whole details in OData service and then during binding to table I will apply filter.
The purpose of the sap.ui.model.Filter class is usually to apply filters to lists on the UI. For example, if you have a list of items and you want to limit that list to a subset of items which fulfills certain criteria.
But what you have here appears to be a classic master-detail scenario where you have a list of items and then when the user selects one show more information about that one item.
The usual solution for such a scenario is to assign the full model to the detail-view and then use an element binding (also known as "context binding") on the view to tell it which item to display.
When the source of the item is a click on an element which already had an element binding, then you can actually retrieve the correct binding path from the click event and just apply it to your detail-view.
From one of the official demos:
onItemSelected: function(oEvent) {
var oSelectedItem = oEvent.getSource();
var oContext = oSelectedItem.getBindingContext("products");
var sPath = oContext.getPath();
var oProductDetailPanel = this.byId("productDetailsPanel");
oProductDetailPanel.bindElement({ path: sPath, model: "products" });
}
When you don't have any convenient way to get an element path from, then you have to construct one yourself:
var detailPanel = this.getView().byId("idOfDetailPanel");
detailPanel.bindElement("PdetailSet(Laufi = " + spayid +", Laufd = " + spaydt + ")");
The latter code snippet does of course assume that the oData-service actually supports access with a key consisting of laufi and laufd. This is decided by:
The definition of the key fields of the entity type in the SAP Gateway Service Builder (transaction SEGW)
The ABAP implementation of the method get_entity of the data provider class of that oData-service.

How to exclude multiple values in OData call?

I am creating a SAPUI5 application. This application is connected to a backend SAP system via OData. In the SAPUI5 application I use a smart chart control. Out of the box the smart chart lets the user create filters for the underlying data. This works fine - except if you try to use multiple 'not equals' for one property. Is there a way to accomplish this?
I found out that all properties within an 'and_expression' (including nested or_expressions) must have unique name.
The reason why two parameters with the same property don't get parsed into the select options:
/IWCOR/CL_ODATA_EXPR_UTILS=>GET_FILTER_SELECT_OPTIONS takes the expression you pass and parses it into a table of select options.
The select option table returned is of type /IWCOR/IF_ODATA_TYPES=>EDM_SELECT_OPTION_T which is a HASHED TABLE .. WITH UNIQUE KEY property.
From: https://archive.sap.com/discussions/thread/3170195
The problem is that you cannot combine NE terms with OR. Because both parameters after the NE should not be shown in the result set.
So at the end the it_filter_select_options is empty and only the iv_filter_string is filled.
Is there a manual way of facing this problem (evaluation of the iv_filter_string) to handle multiple NE terms?
This would be an example request:
XYZ/SmartChartSet?$filter=(Category%20ne%20%27Smartphone%27%20and%20Category%20ne%20%27Notebook%27)%20and%20Purchaser%20eq%20%27CompanyABC%27%20and%20BuyDate%20eq%20datetime%272018-10-12T02%3a00%3a00%27&$inlinecount=allpages
Normally I want this to exclude items with the category 'Notebook' and 'Smartphone' from my result set that I retrieve from the backend.
If there is a bug inside /iwcor/cl_odata_expr_utils=>get_filter_select_options which makes it unable to treat multiple NE filters of the same component, and you cannot wait for an OSS. I would suggest to wrap it inside a new static method that will make the following logic (if you will be stuck with the ABAP implementation i would try to at least partially implement it when i get time):
Get all instances of <COMPONENT> ne '<VALUE>' inside a () (using REGEX).
Replace each <COMPONENT> with <COMPONENT>_<i> so there will be ( <COMPONENT>_1 ne '<VALUE_1>' and <COMPONENT>_2 ne '<VALUE_2>' and... <COMPONENT>_<n> ne '<VALUE_n>' ).
Call /iwcor/cl_odata_expr_utils=>get_filter_select_options with the modified query.
Modify the rt_select_options result by changing COMPONENT_<i> to <COMPONENT> again.
I can't find the source but I recall that multiple "ne" isn't supported. Isn't that the same thing that happens when you do multiple negatives in SE16, some warning is displayed?
I found this extract for Business ByDesign:
Excluding two values using the OR operator (for example: $filter=CACCDOCTYPE ne ‘1000’ or CACCDOCTYPE ne ‘4000’) is not possible.
The workaround I see is to select the Categories you actively want, not the ones you don't in the UI5 app.
I can also confirm that my code snippet I've used a long time for filtering also has the same problem...
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MGW_ABS_DATA->FILTERING
* +-------------------------------------------------------------------------------------------------+
* | [--->] IO_TECH_REQUEST_CONTEXT TYPE REF TO /IWBEP/IF_MGW_REQ_ENTITYSET
* | [<-->] CR_ENTITYSET TYPE REF TO DATA
* | [!CX!] /IWBEP/CX_MGW_BUSI_EXCEPTION
* | [!CX!] /IWBEP/CX_MGW_TECH_EXCEPTION
* +--------------------------------------------------------------------------------------</SIGNATURE>
METHOD FILTERING.
FIELD-SYMBOLS <lt_entityset> TYPE STANDARD TABLE.
ASSIGN cr_entityset->* TO <lt_entityset>.
CHECK: cr_entityset IS BOUND,
<lt_entityset> IS ASSIGNED.
DATA(lo_filter) = io_tech_request_context->get_filter( ).
/iwbep/cl_mgw_data_util=>filtering(
exporting it_select_options = lo_filter->get_filter_select_options( )
changing ct_data = <lt_entityset> ).
ENDMETHOD.

AdWords PLACEMENT_PERFORMANCE_REPORT not pulling URLs

This should be extremely simple but for some reason it doesn't seem to work. I'm trying to pull the URLs of display placements using the DISPLAY_PERFORMANCE_REPORT but instead of URLs it's just returning "--".
The code I'm using is:
var report = AdWordsApp.report(
"SELECT CampaignName, Clicks, FinalAppUrls, FinalUrls " +
"FROM PLACEMENT_PERFORMANCE_REPORT " +
"WHERE Clicks > 0 " +
"DURING LAST_30_DAYS");
var rows = report.rows();
while (rows.hasNext()) {
var row = rows.next();
var url = row["FinalUrls"];
Logger.log(url);
}
I've tried logging the CampaignName and clicks and they're working as expected, so can't understand what the issue is here. The only thing I can think of is that in the reference guide it says:
List of final URLs of the main object of this row. UrlList elements
are returned in JSON list format
I'm not entirely sure what JSON list format is, but when I log the typeof url it says it's a string, so thought it shouldn't be an issue.
The FinalAppUrls and FinalUrls list the target URLs that you set on the individual managed placements.
If you're interested in the URL (domain, rather) of the placement itself, you'll have to request either the Criteria or the DisplayName field in your report——they both contain the domain of the placement.

Sqlite.swift live search

I want to do a live search on the DB.
Lets say I want to search by companies and I have the following info on a column named companies.
Facebook
FastCompany
Facebook
Google
Microsoft
I have a textfield that has calls a function on editchanged.
#IBAction func searching(sender: AnyObject) {
tempstring = "%"+searchBar.text+"%"
println(tempstring)
user = user.select(name)
.filter(like(tempstring, name))
.limit(30, offset: 0)
collectionView?.reloadData()
}
It kind of works, if I start typing "fa"
It will show (Facebook, Facebook and FastCompany)
If I continue typing "fac" it will show (Facebook, Facebook)
But when I delete the last character "c" from the searchbox (leaving it in "fa" again) then the query displays nothing.
Any ideas on how I can solve this.
I think your issue is coming from over writing the user object with each search. This is fine as long as you only move forward, but when you go backwards like you did, the query messes up.
Instead, try adding a currentQuery property to your view controller with the collection view in it and set it to your user.select statement.
currentQuery = user.select(name)
.filter(like(tempstring, name))
.limit(30, offset: 0)
Then use the currentQuery object to display the results instead. This way, no matter what you're searching, it will match everything.

PXDatabase should accept PXDbType.Udt in Acumatica ERP

How can I call a stored procedure in Acumatica via PXDataBase which has as input parameter User defined type?
For example, I have the following type:
CREATE TYPE [dbo].[string_list_tblType] AS TABLE(
[RefNbr] [nvarchar](10) NOT NULL,
PRIMARY KEY CLUSTERED
(
[RefNbr] ASC
)WITH (IGNORE_DUP_KEY = OFF)
)
GO
I have the following stored procedure:
CREATE PROCEDURE [dbo].[GetListOfAPInvoices]
#APInvoices as string_list_tblType readonly,
AS
BEGIN
select * from APInvoice a where a.RefNbr in (select RefNbr from #APInvoices)
END
and following fragment of C# code:
var par = new SqlParameter("APInvoices", dt);
par.SqlDbType = SqlDbType.Structured;
par.TypeName = "dbo.string_list_tblType";
par.UdtTypeName = "dbo.string_list_tblType";
par.ParameterName = "APInvoices";
PXSPParameter p1 = new PXSPInParameter("#APInvoices", PXDbType.Udt, par);
var pars = new List<PXSPParameter> { p1};
var results = PXDatabase.Execute(sqlCommand, pars.ToArray());
but when I execute my C# code I'm receiving error message:
UdtTypeName property must be set for UDT parameters
When I debugged with reflector class PXSqlDatabaseProvider, method
public override object[] Execute(string procedureName, params PXSPParameter[] pars)
I noticed that
using (new PXLongOperation.PXUntouchedScope(Thread.CurrentThread))
{
command.ExecuteNonQuery();
}
command.Parameters.Items has my method parameters, but item which is related to Udt type is null. I need to know how to pass user defined table type. Has anybody tried this approach?
Unfortunately UDT parameters are not supported in Acumatica's PXDatabase.Execute(..) method and there is no way to pass one to a stored procedure using the built-in functionality of the platform.
Besides, when writing data-retrieval procedures like the one in your example, you should acknowledge that BQL-based data-retrieval facilities do a lot of work to match company masks, filter out records marked as DeletedDatabaseRecord and apply some other internal logic. If you chose to fetch data with plain select wrapped into a stored procedure you bypass all this functionality. Hardly is this something that you want to achieve.
If you absolutely want to use a stored procedure to get some records from the database but don't want the above side-effect, one option is to create an auxiliary table in the DB and select records into it using a procedure. Then in the application you add a DAC mapped to this new table and use it to get data from the table by means of PXSelect or similar thing.
Coming back to your particular example of fetching some ARInvoices by the list of their numbers, you could try using dynamic BQL composition to achieve something like this with Acumatica data access facilities.

Resources