Can specify in the where clause that I want the data that has the column value equal to some values from an array?
For example:
EntityQuery.from('Customers')
.where('DepartmentID','in','[3,5,6]');
Or how else should I do it efficiently since the table has a lot of entries an it wouldn't be efficient to retrieve all of them? Is it efficient if I do it one by one?
Using Breeze's new JSON query feature introduced in 1.5.1, you can create a “WHERE value IN array” clause like this:
var jsonQuery = {
from: 'Customers',
where: {
'DepartmentID': { in: [3,5,6] }
}
}
var query = new EntityQuery(jsonQuery);
Just add multiple predicates -
var myArray = [3, 4, 5];
var predicate = new Breeze.Predicate;
var query = EntityQuery.from('Customers');
if (myArray) {
var criteriaPredicate = null;
$.each(myArray, function (index, item) {
criteriaPredicate = (index === 0)
? Predicate.create('DepartmentId', '==', item)
: criteriaPredicate.or('DepartmentId', '==', item);
if (Predicate.isPredicate(criteriaPredicate)) {
predicate = predicate.or(criteriaPredicate);
}
});
}
query = query.where(predicate);
That may not run 100% correctly but should show you what to do - create predicates dynamically and add them to a total predicate and then to the query.
A bit late to the party but I needed the same thing as was able to do it like this:
public getFeaturedRestaurants(restaurantIds: number[]) {
this.dataBreezeService.initialiseQuery('getFeaturedRestaurants', [restaurantIds]);
let query = new EntityQuery()
.from('restaurants')
.where("restaurantId", "in", restaurantIds)
.toType('Restaurant')
.expand('foodType, suburb.city')
return this.dataBreezeService.executeQueryCacheOrServerForList(query, false);
}
Related
I'm doing KPI's in node-red, and I'm using node-red-node-firebird to connect my database and get the results from it. For that I made a query to select the columns I need, one of those is:
NAME Varchar(40), with an example value: "Pizzas"
(example: Select NAME from mytable)
When I receive the query response on node-red, I store it inside the msg.payload. The problem is the result that I get it isn't the string "Pizzas" but a buffer "NAME":{"type":"Buffer","data":[80,105,122,122,97,115]}}.
How can I get the string and not the buffer?
I already tried a lot of things, among them:
On the query I have tried cast(NAME AS varchar(40)) AS NAME; [NAME] without success. Put msg.payload.data.toString('utf-8') in function node but nothing happens, the function:
var objectData = msg.objectData; //this is the query response
//------------Columns----------------------------
var fields = [];
var i = 0;
if(objectData.length > 0) {
var data = objectData[0];
for(var key in data) {
fields[i] = key;
i++;
}
//TRY nº1
objectData.foreach(function(obj){
if (Buffer.isBuffer(obj) === true) {
obj = obj.toString('utf-8');
}
})
}
//-----------------------------------------
msg.method = "POST";
msg.url = //My api request//;
msg.headers = {};
msg.headers["Content-Type"] = "application/json";
msg.headers.Authorization = //auth//;
msg.payload = {
'groupID': 'Group123',
'companyID': 1221,
'table': 'DemoTable',
'fields': fields,
'data': objectData, //problem
'delete': true,
};
//TRY nº2
msg.payload = msg.payload.data.toString('utf-8');
return msg;
I solved my problem changing the select to:
SELECT cast(name as varchar(100) character set win1252) NOME FROM mytable
Thanks for the help :)
In my App I have an array of objects 'class: EventObjects' with several properties like 'date: NSDate?' and 'stuffToDo: String?' that are fetched from a calendar database. What I try to achieve now is putting all EventObjects with the same date property together in another object of 'class: EventsAtSameDate'.
class EventsAtSameDate: NSObject
{
var date:NSDate?
var eventObjects:NSArray<EventObject>?
}
And finally have a nested array with the EventsAtSameDate.
var nestedArrayOfEventsAtSameDateObjects: Array<EventsAtSameDate>?
I know how to search and sort an array with .filter .sort .sortInPlace etc. functions. But how can I compare the dates in the array with each other and put them in another nested Array?
You could instantiate a dictionary to keep track of the dates present while doing one iteration over the initial array of type EventObject. Then iterate the the dictionary to instantiate classes of EventsAtSameDate and append them to the nestedArrayOfEventsAtSameDateObjects: [EventsAtSameDate]
The code would look something like:
var nestedArrayOfEventsAtSameDateObjects = [EventsAtSameDate]()
//instantiate a dictionary that uses Date as the key and an array of EventObject as the associated value
var dictionary = [Date: [EventObject]]()
//iterate through your intial array of EventObjects
for obj in eObjs {
//check if you have already seen the date in the collection
if dictionary[obj.date] != nil {
//if you have - then append it to that date
dictionary[obj.date]?.append(obj)
continue
}
//otherwise, add it to the dictionary for a check later in the loop
dictionary[obj.date] = [obj]
}
//then iterate through the dictionary
for (date, eObjs) in dictionary {
if eObjs.count > 1 {
let sameDate = EventsAtSameDate()
sameDate.date = date
sameDate.eventObjects = eObjs
nestedArrayOfEventsAtSameDateObjects.append(sameDate)
}
}
I would sort the array of your events by date and then iterate over them. Check if the date is newer then the previous one and create another storage if so.
class Event {
var date:Date!
}
class EventsList
{
var date:Date!
var events:[Event]!
}
func createEventsLists(sortedEvents: [Event]) -> [EventsList] {
guard sortedEvents.count > 0 else { return [] }
var currentEventList = EventsList()
var result = [currentEventList]
var lastDate = sortedEvents.first!.date
for event in sortedEvents {
let newDate = event.date.compare(lastDate!) != .orderedDescending
if newDate {
currentEventList = EventsList()
result.append(currentEventList)
}
currentEventList.events.append(event)
lastDate = event.date
}
return result
}
I have 2 Realm Models:
class CourseModel: Object {
dynamic var coursename = ""
dynamic var par3field = 0
dynamic var par4field = 0
dynamic var par5field = 0
let scoreModels: List<ScoresModel> = List<ScoresModel>()
override internal static func primaryKey() -> String? { return "coursename" }
}
class ScoresModel: Object {
dynamic var dateplayed = ""
var courseModel: CourseModel? {
return linkingObjects(CourseModel.self, forProperty: "scoreModels").first
}
}
The app user will first add a new course for which I use CourseModel. As the user plays a course they enter scores for that course, for which I use ScoresModel, hence the primary key 'coursename'.
I query the CourseModel with
let realm = try Realm()
let results = realm.objects(CourseModel)
return results
and it produces the following result
Results<CourseModel> (
[0] CourseModel {
coursename = First Course;
par3field = 4;
par4field = 10;
par5field = 4;
scoreModels = RLMArray <0x797a36d0> (
[0] ScoresModel {
dateplayed = Apr 5, 2016; },
[1] ScoresModel {
dateplayed = Mar 3, 2016; }
);
},
[1] CourseModel {
coursename = Second Course;
par3field = 4;
par4field = 10;
par5field = 4;
scoreModels = RLMArray <0x7a046f40> (
[0] ScoresModel {
dateplayed = Apr 5, 2016; }
);
}
)
The ScoresModel produces a similar result but without the CourseModel data.
The ScoresModel has a lot of data in it, I only showed 'dateplayed' here to keep it short.
My question is this; when I've extracted the data from Realm how can I access a particular field to work with that data, i.e. how do I get the par5field data to do calculations with it, and also the 2nd question how do I get to the scoreModels data, for example 'dateplayed' to list the dates in a table for example?
When you perform a query against Realm, the results are returned in a Results object that behaves exactly like an array. So you need to iterate through each object to access the properties you want for each one.
To answer your first question, to access the par5field property (From just the first object):
let firstObject? = results.first
let par5field = firstObject.par5field
// Do calculations with it
For your second question, scoreModels is just a standard array object, so you can just insert the values it into a table view as you would a standard Array object.
If you wanted to list ALL of the ScoreModel objects, regardless of which CourseModel objects they belong to, you can perform a Realm query to get them directly.
let realm = try! Realm()
let results = realm.objects(ScoreModel)
return results
I'm trying to implement a search by Core Data key, in Swift. I want to get back relevant results, both exact and proximate, sorted in order of distance (from the closest match to the most distant).
For example, if someone searches for, say, "friend", I want the search results to look something like the following: "friend", "friends", "friendly", and "friand".
I've tried my best to implement such a search, but I'm fairly new to this sort of code, and my attempted implementation is not quite working for me at the moment. This is my code:
var request = NSFetchRequest(entityName: "db")
request.returnsObjectsAsFaults = false
request.predicate = NSPredicate(format: "dbKey MATCHES %#", ".*" + searchString + ".*")
var results: Array = context.executeFetchRequest(request, error: nil)!
if (results.count > 100) {
results.removeRange(Range(start: 100, end: results.count-1))
}
var sortedResults: Array = [results[0]]
for (var i = 1; i < results.count; ++i) {
if (countElements(results[i].valueForKey("dbKey") as String) < countElements(sortedResults[i-1].valueForKey("dbKey") as String)) {
var j = i-1
while (countElements(results[i].valueForKey("dbKey") as String) < countElements(sortedResults[j].valueForKey("dbKey") as String)) {
if (j != 0) {
--j
} else {
break
}
}
sortedResults.insert(results[i], atIndex: j)
} else {
sortedResults.append(results[i])
}
}
results = sortedResults
The problem is twofold:
Firstly, the results come back in no particular order, so if I search for "a", I'm going to get back a huge amount of words containing "a" long before I get the exact match. Since I cut off after the first 100 results, I never get the exact match to show up in my results.
Secondly, the ranking is approximate. This is probably a maths error on my part, but currently, many longer words show up before shorter words, so you don't see exact or near-exact matches at the top of the results list, as you should.
I tried to find a library which would incorporate search functionality of the kind I am looking for (something like Fuse.js), but I've had no luck. Any help would be most appreciated.
You could filter your results using different predicates and decide which one to use;
let result = NSPredicate(format: "dbKey CONTAINS[cd] %#", searchString)
let result = NSPredicate(format: "dbKey startsWith[cd] %#", searchString)
let result = NSPredicate(format: "dbKey LIKE '%#'", searchString)
For particular order, you should use NSSortDescriptor
Not an actual answer to your question, but a solution to what you're trying to do still: have a look at PermissiveResearch.
It would look something like this:
extension UIViewController: PermissiveResearchDelegate {
// Call this once
func rebuildDatabase() {
PermissiveResearchDatabase.sharedDatabase().delegate = self
for db in allDbs { // Assuming allDbs is your array of DB objects
PermissiveResearchDatabase.sharedDatabase().addManagedObject(db, forKey: "dbKey")
}
}
// A basic search method
func search(searchString: String) {
PermissiveResearchDatabase.sharedDatabase().searchString(searchString, withOperation: ScoringOperationTypeExact)
}
// PermissiveResearchDelegate method
func searchCompletedWithResults(results: [AnyObject]!) {
let pResults = results as! [PermissiveCoreDataObject]
for result in pResults {
let db = try! self.managedObjectContext.existingObjectWithID(result.objectID) as! DB
print("\(result.score) - \(db.dbKey)")
}
}
}
is there a possibility to get an object from an array with an specific property? Or do i need to loop trough all objects in my array and check if an property is the specific i was looking for?
edit: Thanks for given me into the correct direction, but i have a problem to convert this.
// edit again: A ok, and if there is only one specific result? Is this also a possible method do to that?
let imageUUID = sender.imageUUID
let questionImageObjects = self.formImages[currentSelectedQuestion.qIndex] as [Images]!
// this is working
//var imageObject:Images!
/*
for (index, image) in enumerate(questionImageObjects) {
if(image.imageUUID == imageUUID) {
imageObject = image
}
}
*/
// this is not working - NSArray is not a subtype of Images- so what if there is only 1 possible result?
var imageObject = questionImageObjects.filter( { return $0.imageUUID == imageUUID } )
// this is not working - NSArray is not a subtype of Images- so what if there is only 1 possible result?
You have no way to prove at compile-time that there is only one possible result on an array. What you're actually asking for is the first matching result. The easiest (though not the fastest) is to just take the first element of the result of filter:
let imageObject = questionImageObjects.filter{ $0.imageUUID == imageUUID }.first
imageObject will now be an optional of course, since it's possible that nothing matches.
If searching the whole array is time consuming, of course you can easily create a firstMatching function that will return the (optional) first element matching the closure, but for short arrays this is fine and simple.
As charles notes, in Swift 3 this is built in:
questionImageObjects.first(where: { $0.imageUUID == imageUUID })
Edit 2016-05-05: Swift 3 will include first(where:).
In Swift 2, you can use indexOf to find the index of the first array element that matches a predicate.
let index = questionImageObjects.indexOf({$0.imageUUID == imageUUID})
This is bit faster compared to filter since it will stop after the first match. (Alternatively, you could use a lazy sequence.)
However, it's a bit annoying that you can only get the index and not the object itself. I use the following extension for convenience:
extension CollectionType {
func find(#noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Self.Generator.Element? {
return try indexOf(predicate).map({self[$0]})
}
}
Then the following works:
questionImageObjects.find({$0.imageUUID == imageUUID})
Yes, you can use the filter method which takes a closure where you can set your logical expression.
Example:
struct User {
var firstName: String?
var lastName: String?
}
let users = [User(firstName: "John", lastName: "Doe"), User(firstName: "Bill", lastName: "Clinton"), User(firstName: "John", lastName: "Travolta")];
let johns = users.filter( { return $0.firstName == "John" } )
Note that filter returns an array containing all items satisfying the logical expression.
More info in the Library Reference
Here is a working example in Swift 5
class Point{
var x:Int
var y:Int
init(x:Int, y:Int){
self.x = x
self.y = y
}
}
var p1 = Point(x:1, y:2)
var p2 = Point(x:2, y:3)
var p3 = Point(x:1, y:4)
var points = [p1, p2, p3]
// Find the first object with given property
// In this case, firstMatchingPoint becomes p1
let firstMatchingPoint = points.first{$0.x == 1}
// Find all objects with given property
// In this case, allMatchingPoints becomes [p1, p3]
let allMatchingPoints = points.filter{$0.x == 1}
Reference:
Trailing Closure
Here is other way to fetch particular object by using object property to search an object in array.
if arrayTicketsListing.contains({ $0.status_id == "2" }) {
let ticketStatusObj: TicketsStatusList = arrayTicketsListing[arrayTicketsListing.indexOf({ $0.status_id == "2" })!]
print(ticketStatusObj.status_name)
}
Whereas, my arrayTicketsListing is [TicketsStatusList] contains objects of TicketsStatusList class.
// TicketsStatusList class
class TicketsStatusList {
internal var status_id: String
internal var status_name: String
init(){
status_id = ""
status_name = ""
}
}