Doctrine: remove, then persist with Unique Values - doctrine-orm

I have the following code. The code column of Part requires an unique value and so it throws an error when I remove(), then persist() a row with the same code value. However, the row is supposed to be removed first so there is only one value. Must I run flush() in between those commands?
if ($existingPart) { # we found one
if ($existingPart->getPrice() != $part->getPrice()) { # price changed
$em->remove($existingPart); #soft-delete the old one
$em->persist($part); # persist the new part
$countUpdates++; # get number of updated entities
}
} else {
$em->persist($part); # no existing part with same code, just add new part
$count++; # get number of new commits
}
}
$em->flush();

Ah. I found out why: I am using softdeletable. What I needed to do is remove the unique value flag from the column definition and rather insert the following in the class annotation:
#UniqueEntity(fields={"deletedAt","code"})
This will make it check for whether the combination of deletedAt and code is unique rather than just field.

Related

Django update model in shell not saving

I´m trying to update the data of an existing model with a csv. I read the file and assign the values with no problem.
If I try `MyModel.update() everything runs with no error but the data is not saved.
with open('Productosold.csv') as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
p = ProductosBase.objects.filter(codigo_barra = row['codigo_barra'])
p.region=row['region']
p.producto_ing=row['producto_ing']
p.packaging_ing=row['packaging_ing']
p.precio_compra=row['precio_compra']
p.uom=row['uom']
p.units_inner=row['units_inner']
p.inner_master=row['inner_master']
p.tier=row['tier']
p.precio_lista_internacional=row['precio_lista_internacional']
p.update()
I usualy upload new data using the MyModel.save() method and have no problem.
Now, if I use that I get "Queryset has no attribute save".
p.save()
If I print some of the p.values I can see they are populated correctly from the csv file.
What I´m doing wrong?
Thanks in advance!
.filter always returns a queryset, not a single instance. When you set all those values, you are just setting (previously non-existing) attributes onto that queryset object; you are not setting fields in a model instance. You should use .get to get an instance and save that.
p = ProductosBase.objects.get(codigo_barra = row['codigo_barra'])
p.region=row['region']
...
p.save()
However, since all the columns in your CSV map precisely to fields on the model, you could in fact use filter and update to do the whole thing in one go:
for row in reader:
ProductosBase.objects.filter(codigo_barra=row['codigo_barra']).update(**row)
and no need for any of the rest of the code.
You need filter() whenever you expect more than just one object that matches your criteria. If no item was found matching your criteria, filter() returns am empty queryset without throwing an error.
Also you can use get() but when you expect one (and only one) item that matches your criteria. Get throws an error if the item does not exist or if multiple items exist that match your criteria. You should therefore always use if in a try.. except .. block or with a shortcut function like get_object_or_404 in order to handle the exceptions properly. I'd recommend using get_object_or_404 in this case.
p = get_object_or_404(ProductosBase, codigo_barra=row['codigo_barra'])

Ordering Sitecore search results

I have a IQueryable<T> object as search results object.
I apply the filtering and sorting on this search object.
Before I call the GetResults(), I want to order the results based on one of the field's (Fieldname - Priority) value. So for all the items in the IQueryable<T> object, I want to order them desc by Priority field, so all the items which has a value for that field stay at the top and the rest are at the bottom.
I have the fieldmap entry for Priority field.
search.OrderByDescending(i => !string.IsNullOrEmpty(i.GetItem().GetFieldValue("Priority")))
The above command doesn't work. Apparently, I can't use Sitecore extension methods with IQueryable?
If I convert search.ToList(). Do the ordering and then convert it back to AsQueryable(), I get the following error:
There is no method 'GetResults' on type 'Sitecore.ContentSearch.Linq.QueryableExtensions'
that matches the specified arguments
Is there a neat and quick way to get around this?
Cheers
I think you just need to add your field to your SearchResultItem and mark it as an int. I am making the assumption that the field is an int. Make a custom class that inherits SearchResultItem.
public class CustomSearchResultItem : SearchResultItem
{
[IndexField("Priority")]
public int Priority { get; set; }
}
Then use it in your search. Finally order by it.
using (var context = ContentSearchManager.GetIndex("sitecore_master_index").CreateSearchContext())
{
var results = context.GetQueryable<CustomSearchResultItem>().Where(prod => prod.Content.Contains("search box text").OrderByDescending(t => t.Priority);
}
Some data found here.
http://www.sitecore.net/learn/blogs/technical-blogs/sitecore-7-development-team/posts/2013/10/sorting-and-ordering-results.aspx
You can order search results using multiple fields by using the OrderByDescending combined with ThenByDescending. So you would need to order by Priority and then by [Name|Date|Whatever].
I want to order them desc by Priority field, so all the items which has a value for that field stay at the top and the rest are at the bottom.
I sort them first on the criteria chosen by the user - like Name, Date created etc. Once I get the results back, I need to order them by priority field
You are conflicting yourself in the questions and comments. If you want the results with priority first and then by user selected results then the following will work:
query = dataQuery.OrderByDescending(i => i.Title).ThenByDescending(i => i["Priority"]);
var results = query.GetResults().Hits.Select(h => h.Document);
There was a bug in earlier version of Sitecore which meant that the ThenBy clause will be added before the OrderBy clause hence it is added in reverse above. You may want to check if this is fixed in the current version. If so simply change your query to:
query = dataQuery.OrderByDescending(i => i["Priority"]).ThenByDescending(i => i.Title);
You don't have to add the field to your SearchResultItem if you just want to order by it, only if you need the actual value of that field returned to as well.
If you need to order by a custom user supplied value then you can pass in i => i["whatever-field-the-user-has-selected"] instead of i.Title.
You can find more info in this blog post.

How to update the value of a specific column of every row in DB with the output of a function that was passed in the original value.

For example: if you wanted to replace in each row the value of a column with the value after being run through a hash function.
In my case I have saved many URLs in a column that have 302 redirects and I want to save where they redirect to after passing their current value into this function:
def finalURL(original):
output = requests.get(original)
output.url
return output.url
I am relatively new to Python and the closest examples I can find are not written in Python (cannot translate).
Additionally I've seen several posts on how to iterate through a db and print every value in a column, but no explanation on how to change that value.
To make your hash function available in SQLite, you have to create a user-defined function:
def finalURL(x):
return ...
db = sqlite3.connect(...)
db.create_function("finalURL", 1, finalURL)
Then you can simply use it in queries:
db.execute("UPDATE MyTable SET url = finalURL(url) WHERE ...")

how to use 'select limit 1' in rails 4.1

I want to use this code:
select id from categories where hotel_id=4 limit 1
I am new in rails. How do i use activerecord in controller to achieve the same result as the above code.
I already have hotel_id in params in my controller.
Try in your controller this:
#category = Category.where(:hotel_id => 4).limit(1)
OR
#category = Category.where(:hotel_id => 4)
It will return all the data from categories table which has hotel_id as 4
You can check it by write this line next to above code.
abort #category.inspect # to check in browser what does this object contains
If you want first data from the object then you can write #category.first same as for last entry #category.last after first line..
If you need only one first match record then you can use find_by
#category = Category.find_by(:hotel_id => 4)
The right answer would be using limit(1) reference
Using first or last actually runs the whole query then returns the first element only, would perform badly if the result set is large.
So just stick with limit
EDIT:
I just checked and i found that using first and last do actually add limit statement to the query, so I guess they are also just as correct as limit(1)
You can use .limit(1) or .first or .last
Model.where(hotel_id: 4).limit(1)

Search & replace row by row, letter by letter in table using Python

I wrote a script for ArcMap using python that would take a table with unsupported characters, Romanize or transliterate those applicable fields, and create a shapefile with any geographic information that might also be contained in the table. The rest of the code I have determined is working alright. My main problem is the ability to search letter by letter within each row of the input table, which I had working earlier but I guess I reverted to an earlier error.
# Loop through each row in the copied table and replacing each cell with one based on the reference table.
rows = access.SearchCursor(outtable, orfield) # Creates a search cursor that looks in the outtable for what is in the native language field.
row = rows.next() # Establishes a variable that cycles row to row.
while row: # Beginning of "while" loop.
for r in row: # Searches each letter within the searched row.
for o in orfield: # Searches each cell based on the searched field from the reference table.
if r == o: # If/Else statement for seeing if the letter being searched for in the intable (r) is identical to the letter in the orthography field (o).
r.replace(orfield, profield) # Replaces any identical letters with the associated pronunciation.
else:
row.next() # Cycles to the next row.
I feel like I'm missing something but not quite sure. If you need me to elaborate more on what else is contained in my script, let me know. Don't necessarily need to write the script for me but if there's a module or function that I could you, let me know what it is and where I can read about it.
A little fuzzy on some of your details but it appears the code is attempting to compare a Field data object (created w/for r in row) with the elements in some input set, which you seem to imply is a string. Aside from the type mismatch of Field vs string, I believe that a Row object is not iterable the way you've written it. You can get the fields with something like:
fldList = list()
for fld in arcpy.ListFields(r'C:\Workspace\somedata.shp'):
fldList.append(fld.name)
and then iterate of fldList using something like:
for fld in fldList:
fldValue = row.getValue(fld)
....do some regex/string parsing
....if condition met, use row.setValue(fld, newValue) and rows.update(row)