I have a query (a Query object):
$joblineitems = $this->JobLineItems->find('all');
It has results (a ResultSet object):
$joblineitemsresults = $joblineitems->all();
The ResultSet object is an Iterable such that a foreach() loop will return each of the JobLineItem objects.
I simply want to add an additional result to $joblineitemsresults - specifically I want to append a $this->JobLineItems->newEntity() to the end of the results so that when I subsequently paginate $joblineitemsresults and loop through it in the view, the last object in the loop on the last page will be a blank object with the property new=true.
How can I manually append an extra result to a ResultSet object?
try this
$joblineitems = $this->JobLineItems->find('all');
$joblineitemsresults = $joblineitems->all();
$joblineitemsresults = $joblineitemsresults ->append([$this->JobLineItems->newEntity()]);
debug($joblineitemsresults ->toList());
You can see the manual for reference
pay attention in particular to the last paragraph
When appending from different sources, you can expect some keys from
both collections to be the same. For example, when appending two
simple arrays. This can present a problem when converting a collection
to an array using toArray(). If you do not want values from one
collection to override others in the previous one based on their key,
make sure that you call toList() in order to drop the keys and
preserve all values.
That's why I used toList() instead of toArray(). If you use toArray() you'll see the new entity override the first one.
Of course you can also transform your recordset in an array and then append the new entity to the array
$joblineitemsresults = $joblineitems->toArray();
joblineitemsresults[] = $this->JobLineItems->newEntity();
Related
I am trying to create a single search box on my website.
First I split up the search input in multiple strings using split().
Then I am looping over the multiple strings I created with split(), with every string I create a query. These query's will be stored in a list.
In the next step I am trying to execute all those query's and store the results (rows) in another list.
The next thing I want to do is union all these results(rows). In this case the final result will be an output of a query containing all the different keywords used in the searchbox.
This is my code:
def ajaxlivesearch():
str = request.vars.values()[0]
a=str.split()
items = []
q = []
r =[]
for partialstr in a:
q.append((db.profiel.sport.like('%'+partialstr+'%'))|(db.profiel.speelsterkte.like('%'+partialstr+'%'))|(db.profiel.plaats.like('%'+partialstr+'%')))
for query in q:
r.append(db(query).select(groupby=db.profiel.id))
for results in r:
for (i,row) in enumerate(results):
items.append(DIV(A(B(row.id_user.first_name) ,NBSP(1), B(row.id_user.last_name),BR(), I(row.sport),I(','), NBSP(1), I(row.speelsterkte),I(','), NBSP(1),I(row.plaats),HR(), _id="res%s"%i, _href=row.id_user, _onclick="copyToBox($('#res%s').html())"%i), _id="resultLiveSearch"))
return TAG[''](*items)
My question is: How do I union the multiple results(rows)?
You can get the union of two Rows objects (removing duplicates) as follows:
rows_union = rows1 | rows2
However, it would be more efficient to get all the records in a single query. To simplify, you can also use the .contains method rather than using .like and wrapping each term with %s.
fields = ['sport', 'speelsterkte', 'plaats']
query_terms = [db.profiel[f].contains(term) for f in fields for term in a]
query = reduce(lambda a, b: a | b, query_terms)
results = db(query).select()
Also, you are not using any aggregation functions, so it is not clear why you have specified the groupby argument (and in any case, each record has a unique id, so grouping would have no effect). Perhaps you instead meant orderby=db.profiel.id.
Finally, it is probably not a good idea to do request.vars.values()[0], as request.vars is a dictionary-like object, and the particular value of interest is not guaranteed to be the first item in .values(). Instead, just refer to the name of the particular variable (e.g., request.vars.keyword), which is also more efficient because you are extracting a single item rather than converting all values to a list.
I have no idea what is going on here and it's a little bizzare.
I'm adapting a VBA macro into a VB.net project, and I'm experiencing what I would describe as some extreemly unusual behavior of a method I'm using to pass data around in VB.net. Here's the set up...
I have, for indexing reasons, a collection that consists of all open orders:
Public allOpenOrders As New Collection
Within this collection, I store other collections, indexed by account number, that each contain information about each open order in an array that is three elements long. Here is how I'm populating it:
openOrderData(0) = some information
openOrderData(1) = some information
openOrderData(2) = some information
SyncLock allOpenOrders
If allOpenOrders.Contains(accountNumber) Then
'Already in the collection...
accountOpenOrders = allOpenOrders(accountNumber)
accountOpenOrders.Add(openOrderData)
Else
'Not already in collection
accountOpenOrders = New Collection
accountOpenOrders.Add(openOrderData)
allOpenOrders.Add(accountOpenOrders, AccountNumber)
End If
End SyncLock
Here's the thing, if I place a stop after end synclock and check the collection, I can clearly see that the array with all data is there, plain as day. However, when I move on in my code (this is occuring in another thread after the preceeding code has executed) to retrieve it and write it to a workbook...
If allOpenOrders.Contains(accountNumber) Then
accountOpenOrders = allOpenOrders(accountNumber)
For each openOrderArray In accountOpenOrders
OutputSheet.Cells(1, 1).value = accountNumber
For counter = 0 to 2
OutputSheet.Cells(1, counter + 2).value = openOrderArray(counter)
Next counter
Next openOrderArray
End If
I get the first element of the array in column B, but C and D are blank. Even more puzzling, if I put a stop right after the allOpenOrders.Contains line I can look at the collection and the last two elements of the array are now blank. Most puzzling of all, they aren't just blank, they are blanks, a number of blanks equal in length to the original field I recorded in that element of the array?!
Any ideas are appreciated. I can tell you I'm using the same type of method to load other data in this workbook with no problems. These are also the only instances in which the allOpenOrders collection is touched... I'm so confused by these results.
courses, next_cursor, more_results = CourseTable.query()\
.order(CourseTable.name)\
.fetch_page(2, \
start_cursor=current_cursor,\
projection=['name', 'abbrev_name']
list = format_list(courses)
logging.info(list)
def format_list(coursequery):
for x in coursequery:
keyid = x.key.id()
x.school_list = ICTable.school_nameabbrev_from_courseid(courseid=keyid)
x.teacher_list = TCTable.teacherfilter_from_courseid(courseid=keyid)
x.courseid = keyid
full_list.append(x)
return full_list
For the above logic, I am doing a projection query in ndb google datastore and then formatting (i.e. format_list) the returned query with extra fields retreived from other entities. I then append the updated query with the extra fields, but when I do a logging.info display of the list, I do NOT see the added fields (i.e. school_list and teacher_list -- only the fields from the original projection query---ANY BODY have any ideas why??? Thank you so much anyone.
I think you should first convert the returned object into dict and then add the additional fields.
you can use this to convert to dict
https://developers.google.com/appengine/docs/python/ndb/modelclass#Model_to_dict
A projection query returns entities intended to be read-only. An easy workaround would be to convert the data to a dict, as omair says. Try d = x._to_dict().
It actually is saving the data, but the str method on projections only prints the projected fields.
Based on the documentation here:
http://docs.composite.net/Data/AccessingDataWithCSharp/How-to-Query-Data-Using-LINQ#_How_to_Query
I need to query data in a table using a filter in type string[int1,int2,int3..] and can't work out how to go about it.
The string[] comes from a different table field which stores id values of a multiselect element on a form:
Table 'Profile' (AGlobal.profile) contains columns:
Id Types(profile_accomtypes)
1 1,2
2 4,7
3 12,4,6
4 3,6,9
Then I have a static table 'TypeDesc' (ALocal.proptype) listing a total of 12 'Type' values:
Id Description(proptype_names)
1 The first description
2 The second description
........
12 The twelfth description
I created a strongly coded class enabling me to easily handle the form content on submit from the client. Within the form was a couple of multiselects (one of them being 'Types" above in the Profile datatype table.) Each of the multiselects are passed to the server in serialized JSON format where I string.Join the 'Types' values with a comma separator to save into the Profile.Types column.
Now I want to serve the selections in a profile page to the client by loading the Types string[] of Profile Id and using the int id values to filter the TypeDesc table to only select the Type values with Description so that I can render the descriptions as a bullet list on the client.
The filter Types in the Profile table are always id integers
My code I'm using is:
var myProftype =
(from d in connection.Get<AGlobal.profile>() // find multiselected type string values
where d.Id == StUserSet.utoken
select d).First();
string sProftype = myProftype.profile_accomtypes;
string[] sTypes = sProftype.Split(',');
// now filter proptypes to sTypes
var myTAccomtypes =
(from d in connection.Get<ALocal.proptype>() // get all the types from the DB
where(r => sTypes.Contains(r.Field<int>("Id"))) //Lambda ?
select d).All;
StringBuilder sb = new StringBuilder(0); //create a bullet list string
// Loop over strings
foreach (string s in myTAccomtypes)
{
sb.append("<dd>"+ s +"</dd>");
}
TuAccomtypes = sb.ToString(); // pass string to JQuery Taconite as part of AJAX response to alter DOM.
I have an error on the Lambda trying to filter my types.
In VS2010:
Error = Cannot convert lambda expression to type bool because its not a delegate type.
I also do not know how to go about parsing the sTypes variables to int (if I need to) so that the filter works :(
Where am I going wrong? Is there a cleaner way to filter a dataset against a comma separated list queried from a column field within a db table?
Thank you for any help/ideas in advance.
Martin.
I'm not entirely sure about your model, but I think this will work for you. I changed your linq, and combined some statements. I'm also casting your Id field to string so that it can be found correctly in the array.Contains() function. You might want to do the reverse of casting your strings to ints and comparing that way, but that's up to you.
var myProftype = profiles.First(p => p.Id == StUserSet.utoken);
string sProftype = myProftype.profile_accomtypes;
string[] sTypes = sProftype.Split(',');
var myTAccomtypes = propTypes.Where(r => sTypes.Contains(r.Field<int>("Id").ToString()));
StringBuilder sb = new StringBuilder(0);
foreach (PropType s in myTAccomtypes)
{
sb.Append("<dd>" + s.Description + "</dd>");
}
Once splitting the string var from the original Linq query (which identified a single field with a joined string of comma separated id numbers.) I wasn't able to use "Contains" properly.
I cast the second Linq query ToList which evaluated the collection.
Then instead of working with a full result I limited the result to just the id and name fields.
Relying on an article posted by Vimal Lakhera:
http://www.c-sharpcorner.com/uploadfile/VIMAL.LAKHERA/convert-a-linq-query-resultset-to-a-datatable/
I converted the result set into a DataTable which allowed easy looping and selection of fields to output as an html string as part of a JQuery Taconite callback.
Here's what works for me...
// now filter proptypes to selected Types|
var myTAccomtypes = from d in connection.Get<ALocal.proptype>().ToList()
// ToList() will evaluate collection, you cannot pass sTypes array of integers to a sql query, at least not in that way
where sTypes.Contains(d.proptype_id.ToString())
select new { d.proptype_id, d.proptype_name };
DataTable AcomType = LINQToDataTable(myTAccomtypes);
StringBuilder sb = new StringBuilder();
// Loop over table rows
foreach (var row in AcomType.Rows.OfType<DataRow>().Take(19)) // will .Take up to a maximum of x rows from above
{
sb.Append("<dd>");
sb.Append(row["proptype_name"].ToString());
sb.Append("</dd>");
}
HldUserSet.TuAccomtypes = sb.ToString();
//HldUserSet.TuAccomtypes = string.Join(",", myTAccomtypes); //Check query content
Using Vimal's 'LINQToDataTable" with the tweak in the LINQ request means that I can use the class in numerous places of the site very quickly.
This works a treat for those with a single string of joined id's in the form of "2,7,14,16" that need to be split and then used to filter against a wider collection matching the id's from the string to record id numbers in a different collection.
After much googling and console testing I need some help with arrays in rails. In a method I do a search in the db for all rows matching a certain requirement and put them in a variable. Next I want to call each on that array and loop through it. My problem is that sometimes only one row is matched in the initial search and .each causes a nomethoderror.
I called class on both situations, where there are multiple rows and only one row. When there are multiple rows the variable I dump them into is of the class array. If there is only one row, it is the class of the model.
How can I have an each loop that won't break when there's only one instance of an object in my search? I could hack something together with lots of conditional code, but I feel like I'm not seeing something really simple here.
Thanks!
Requested Code Below
#user = User.new(params[:user])
if #user.save
#scan the invites dbtable and if user email is present, add the new uid to the table
#talentInvites = TalentInvitation.find_by_email(#user.email)
unless #talentInvites.nil?
#talentInvites.each do |tiv|
tiv.update_attribute(:user_id, #user.id)
end
end
....more code...
Use find_all_by_email, it will always return an array, even empty.
#user = User.new(params[:user])
if #user.save
#scan the invites dbtable and if user email is present, add the new uid to the table
#talentInvites = TalentInvitation.find_all_by_email(#user.email)
unless #talentInvites.empty?
#talentInvites.each do |tiv|
tiv.update_attribute(:user_id, #user.id)
end
end