I try to delete entries in the database with the active records of Yii. But I think it works really weird.
I want to delete all records of my table where vehicle_id = the given id and plug_id NOT IN (given string)
I tried a lot of ways and nothing worked but this
$query = "delete from `vehicle_details` where `vehicle_id`= ".$vehicle->id." AND `plug_id` NOT IN (".implode(',', array_map(function($item) {
return $item->type;
}, $vehicleDetails->plug)).")";
$command = Yii::app()->db->createCommand($query);
$command->execute();
But why isn't this working???
VehicleDetail::model()->DeleteAllByAttributes(
array('vehicle_id' => $vehicle->id),
array('condition' => 'plug_id NOT IN (:ids)',
'params' => array('ids' => implode(',', array_map(function($item) {
return $item->type;
}, $vehicleDetails->plug)))));
Or this:
VehicleDetail::model()->deleteAll(' vehicle_id = :vehicleId AND plug_id NOT IN (:ids)', array('vehicleId' => $vehicle->id, 'ids' => implode(',', array_map(function($item) {
return $item->type;
}, $vehicleDetails->plug))));
But if I make and Find by attributes out of this query it works well and returns the correct data.
I hope you can explain it to me.
Your code does not work because of wrong arguments passed in the methods. Problems occur when YII tries to build CDbCriteria object using your array arguments. Fortunetly, you can build a CDbCriteria by yourself and pass it into methods directly. Guess in this particular case it will be easier to use a CDbCriteria object to solve the issue.
$dbc = new CDbcriteria();
$dbc->condition = 'vehicle_id = :vehicleId';
$dbc->params = array(':vehicleId'=>$vehicle->id);
$dbc->addNotInCondition(
'plug_id',
array_map(
function($item) {
return $item->type;
},
$vehicleDetails->plug)
);
VehicleDetail::model()->deleteAll($dbc);
That is all you need.
Related
I loop trough an eloquent Collection and I want to add the data to another Collection called "$tagCollection". If an entry with the same tag_id already exists I only want to increase the rating-column for the existing entry.
At the moment it looks like this. Has anyone an Idea?
$tagCollection = collect();
$entries->each(function($entry) use($tagCollection){
$tagId = $entry->tag_id;
//something like this
if($tagCollection->contains('tag_id', $tagId)){
$tagCollection->update ('rating' => $oldRating + 0.5)
} else{
$tagCollection->push(array(
'tag_id' => $tagId,
'rating' => 0.35
));
}
});
I also tried to use ->pull() to remove the Item out of the Collection and then push it again with the new rating but I also do not know how
Can you do it with array instead of collection? For example:
$tagArray = [];
$entries->each(function ($entry) use (&$tagArray) {
if (isset($tagArray[$entry['tag_id']])) {
$tagArray[$entry['tag_id']] += 0.5;
} else {
$tagArray[$entry['tag_id']] = 0.35;
}
});
If the end goal is to update all the entries present in $entries that belong to a specific $tagId, then you can do this
$entryIds = $entries->where('tag_id',$tagId)->pluck('id')->toArray();
Entry::whereIn('id', $entryIds)->update(['rating' => \DB::raw('rating + 0.5')]);
And thats it.
I am new to Cypress [3 days :)]. I am creating a custom command which is trying to find the column index of column in a table.
I want to return the column index and store it in a variable and use it in future steps.
Here is what I have tried:
Cypress.Commands.add('get_table_column_index', (columnName) => {
cy.getIframeBody().find('table').within(() => {
cy.get('tr th[scope=col]').each((element, index) => {
let colName = element.text();
cy.log(index, colName);
if(colName == columnName)
{
cy.wrap(index).as('index');
return false;
}
});
});
});
let columnIndex = cy.get_table_column_index('ColName').get('#index');
cy.log('index' + columnIndex);
index is [object Object]
Can someone please guide me in resolving this issue?
What am I doing wrong?
I can see that wrap is returning the correct index value but I am not sure how to extract and use it.
======= Update =========
I tried this and looks like it was able to log the correct value:
let columnIndex =
cy.get_table_column_index(column_name).get('#index');
columnIndex.then(index => cy.log(index));
Now, I am trying to expand it to use the index value in the next step like this:
Cypress.Commands.add('get_text', (row_num, column_name) => {
let txt;
cy.test_index(column_name).get('#index').then(index => {
let element = cy.get('main > table').within(() => {
cy.log('${index');
cy.get('tr:nth-child(${row_num}) td:nth-child(${index})');
//txt = element.text();
cy.log(txt);
});
});
return txt;
})
I am not able to figure out how to use the value of index and row_num in cy.get('tr:nth-child(${row_num}) td:nth-child(${index})'; expression.
Error: Syntax error, unrecognized expression: :nth-child
All you need to do is change the way that you are using variable.
cy.log(this.index + columnIndex);
I was able to get this working like this:
.get('#index').then(....
was used to extract the value of the index which is returned by my method get_table_column_index.
Then used cy.wrap again to return the cell value.
Cypress.Commands.add('get_text', (row_num, column_name) => {
cy.get_table_column_index(column_name).get('#index').then(index => {
cy.get('main > table').within(() => {
cy.get(`tr:nth-child(${row_num}) td:nth-child(${index})`)
.invoke('text')
.then((text) => {
cy.log("Text = " + text);
return cy.wrap(text).as('cell_value');
})
});
});
})
Then finally in my method call:
let cell_text = cy.get_text(2, 'Licensing').get('#cell_value');
cell_text.then(cell_value => {
cy.log(cell_value);
expect(cell_value).to.include('QTP');
})
The only thing I am not able to do is to store the value in a variable and use it without chaining any command like then to extract its value.
It would be great if someone can provide more information on that.
Thanks.
I am currently trying to figure out how to load an angular/fire-collection including all of its subcollections with RxJS.
This is my current approach:
return this.collectionRef.valueChanges().pipe(
flatMap((entities: Entity[]) => entity),
mergeMap((entity: Entity) => this.setSubCollection1(entity)),
mergeMap((entity: Entity) => this.setSubCollection2(entity)),
scan((entities: Entity[], entity: Entity) => entities.filter(a => a.id !== entity.id).concat(entity), [])
);
and to load the documents in their subcollections
private setSubCollection1 = (entity: Entity): Observable<Entity> => {
return this.subCollectionRef.valueChanges(actor).pipe(
map((subEntities1: SubEntity1[]) => {
entity.subEntities1 = subEntities1;
return entity;
})
);
}
It works fine when having a full stream.
But now I wanted to get all of data in one single Promise: I already tried .first().toPromise() but this only gets the first entry, and does not finish if the collection has no entries. Using reduce in the query also does not work, because valueChanges() never finishes.
Am I using the wrong operators? Or any other ideas on how to solve that?
I hope to hear from you.
I'm working with Lumen framework v5.8 (it's the same as Laravel)
I have a command for read a big XML (400Mo) and update datas in database from datas in this file, this is my code :
public function handle()
{
$reader = new XMLReader();
$reader->open(storage_path('app/mesh2019.xml'));
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName === 'DescriptorRecord') {
$node = new SimpleXMLElement($reader->readOuterXML());
$meshId = $node->DescriptorUI;
$name = (string) $node->DescriptorName->String;
$conditionId = Condition::where('mesh_id', $meshId)->first();
if ($conditionId) {
ConditionTranslation::where(['condition_id' => $conditionId->id, 'locale' => 'fr'])->update(['name' => $name]);
$this->info(memory_get_usage());
}
}
}
}
}
So, I have to find in the XML each DescriptorUI element, the value corresponds to the mesh_id attribute of my class Condition.
So, with $conditionId = Condition::where('mesh_id', $meshId)->first(); I get the Condition object.
After that, I need to update a child of Condition => ConditionTranslation. So I just get the element DescriptorName and update the name field of ConditionTranslation
At the end of the script, you can see $this->info(memory_get_usage());, and when I run the command the value increases each time until the script runs very very slowly...and never ends.
How can I optimize this script ?
Thanks !
Edit : Is there a way with Laravel for preupdate multiple object, and save just one time at the end all objects ? Like the flush() method of Symfony
There is a solution with ON DUPLICATE KEY UPDATE
public function handle()
{
$reader = new XMLReader();
$reader->open(storage_path('app/mesh2019.xml'));
$keyValues = [];
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName === 'DescriptorRecord') {
$node = new SimpleXMLElement($reader->readOuterXML());
$meshId = $node->DescriptorUI;
$name = (string) $node->DescriptorName->String;
$conditionId = Condition::where('mesh_id', $meshId)->value('id');
if ($conditionId) {
$keyValues[] = "($conditionId, '".str_replace("'","\'",$name)."')";
}
}
}
}
if (count($keyValues)) {
\DB::query('INSERT into `conditions` (id, name) VALUES '.implode(', ', $keyValues).' ON DUPLICATE KEY UPDATE name = VALUES(name)');
}
}
I'm using the NEST .NET client (6.3.1), and trying to compose a search query that is based on a number of (optional) parameters.
Here's what i've got so far:
var searchResponse = await _client.SearchAsync<Listing>(s => s
.Query(qq =>
{
var filters = new List<QueryContainer>();
if (filter.CategoryType.HasValue)
{
filters.Add(qq.Term(p => p.CategoryType, filter.CategoryType.Value));
}
if (filter.StatusType.HasValue)
{
filters.Add(qq.Term(p => p.StatusType, filter.StatusType.Value));
}
if (!string.IsNullOrWhiteSpace(filter.Suburb))
{
filters.Add(qq.Term(p => p.Suburb, filter.Suburb));
}
return ?????; // what do i do her?
})
);
filter is an object with a bunch of nullable properties. So, whatever has a value i want to add as a match query.
So, to achieve that i'm trying to build up a list of QueryContainer's (not sure that's the right way), but struggling to figure out how to return that as a list of AND predicates.
Any ideas?
Thanks
Ended up doing it by using the object initialisez method, instead of the Fluent DSL"
var searchRequest = new SearchRequest<Listing>
{
Query = queries
}
queries is a List<QueryContainer>, which i just build up, like this:
queries.Add(new MatchQuery
{
Field = "CategoryType",
Query = filter.CategoryType
}
I feel like there's a better way, and i don't like how i have to hardcode the 'Field' to a string... but it works. Hopefully someone shows me a better way!