Can not remove an item from an array using Sequelize and MYSQL - mysql

I am using MYSQL through Sequelize to build a node.js application with typescript. I created a table and the table has a field which I made a JSON dataType and made it an array by default. I have been able to push items into the array. I would like to remove items from the array, how can I achieve this?
I tried using await category.update({array_Of_food:Sequelize.fn('array_remove',Sequelize.col('array_of_food'),JSON.stringify(category.dataValues.array_Of_food && category.dataValues.array_Of_food[index]))})
I got an error that array_remove does not exist.

I solved my problem this way since I couldn't find an inbuilt way of doing it. I know this is not the best method but at least it works. At the end, I wrote a longer code.
1.Get the string value of the item you want to remove.
const indexString = food.dataValues.food_Name as string;
2.Get the index number of that item inside the array you wish to delete it from:
const index = category.dataValues.array_Of_food?.indexOf(indexString) as number;
3.Create a variable for the the array out of the model colum that you are targeting.
const arrayValue = category.dataValues.array_Of_food
4.Remove that item from the array variable that you crceated:
arrayValue?.splice(index, 1);
5.Use the update method and pass the array variable you deleted the item from as the update: This will replace the initial array values with the new array values. Remember that the new array values contain all the values in the array column excluding the value you deleted.
await category.update({array_Of_food: arrayValue})
This worked!

Related

How to compare the content of 2 columns in functions on object?

I am trying to build a query to match two columns and I have tried the following:
obj= obj.filter(e => e.colOne.exactMatch(e.colTwo))
I am not be able to get this working, is there any way to filter by comparing the content of 2 columns?
The filter() method can't dynamically grab the value to filter based on each object, but can be used to filter on a static value.
You can filter a smaller object set (<100K rows) named myUnfilteredObjects of type ObjectType this way:
let myFilteredObjects = new Set<ObjectType>();
for (const unfilteredObj of myUnfilteredObjects) {
if (unfilteredObj.colOne === unfilteredObj.colTwo) {
myFilteredObjects.add(unfilteredObj);
}
}
Edit: updating with a solution for larger-scale object sets:
You can create a new boolean column in your object's underlying dataset that is true if colOne and colTwo match, and false otherwise. Filtering on this new column via the filter() method will then work as you expect.
It is not possible to compare two columns when writing Functions. A recommended strategy here would be to create a new column that captures your equality. For example in your pyspark pipeline, right before you generate the end objects that get indexed:
df.withColumn("colOneEqualsColTwo", F.when(
F.col("colOne") == F.col("colTwo"), True
).otherwise(False)
And then filter on that new column:
obj = obj.filter(e => e.colOneEqualsColTwo.exactMatch(true))

How to make array from MySQL ROW type?

I am using mysql-native driver. My code:
ResultRange MySQLTablesRange = mysqlconnection.query(`SELECT historysensor FROM TableName`);
auto historysensor = MySQLTablesRange.array.filter!(a=>a[0].coerce!string.canFind("historysensor"));
But on send string I am getting to historysensor not an array, but structure like: Row([historysensor_10774], [false]).
So every time to get value I need to do a lot of casting like:
foreach(sensor;historysensor)
{
writeln(sensor[0].coerce!string.split("_")[1]);
}
How I can make historysensor as simple array, to be able to work without [0].coerce!string?
You can just map it before doing the other stuff
auto historysensor = MySQLTablesRange.array.
map!(a => a[0].coerce!string). // this is new
filter!(a.canFind("historysensor"). // no need for coerce here now
array; // convert to plain array of strings
BTW using filter here is probably a mistake too, make that part of your query so the database does it, that would be likely more efficient and easier to read.

iterate through Poco::JSON::Object in insertion order

It is possible to preserve insertion order when parsing a JSON struct with a
Poco::JSON::Parser( new Poco::JSON::ParseHandler( true ) ): the non-default ParseHandler parameter preserveObjectOrder = true is handed over to the Poco::JSON::Objects so that they keep an private list of keys sorted in insertion order.
An object can then be serialized via Object::stringify() to look just like the source JSON string. Fine.
What, however, is the official way to step through a Poco::JSON::Object and access its internals in insertion order? Object::getNames() and begin()/end() use the alphabetical order of keys, not insertion order -- is there another way to access the values, or do I have to patch Poco?
As you already said:
Poco::JSON::ParseHandler goes into the Poco::JSON::Parser-constructor.
Poco::JSON::Parser::parse() creates a Poco::Dynamic::Var.
From that you'll extract a Poco::JSON::Object::Ptr.
The Poco::JSON:Object has the method "getNames". Beginning with this commit it seems to preserve the order, if it was requested via the ParseHandler. (Poco::JSON:Object::getNames 1.8.1, Poco::JSON:Object::getNames 1.9.0)
So now it should work as expected to use:
for(auto const & name : object->getNames()){
auto const & value = object->get(name); // or one of the other get-methods
// ... do things ...
}

Setting lua table in redis

I have a lua script, which simplified is like this:
local item = {};
local id = redis.call("INCR", "counter");
item["id"] = id;
item["data"] = KEYS[1]
redis.call("SET", "item:" .. id, cjson.encode(item));
return cjson.encode(item);
KEYS[1] is a stringified json object:
JSON.stringify({name : 'some name'});
What happens is that because I'm using cjson.encode to add the item to the set, it seems to be getting stringified twice, so the result is:
{"id":20,"data":"{\"name\":\"some name\"}"}
Is there a better way to be handling this?
First, regardless your question, you're using KEYS the wrong way and your script isn't written according to the guidelines. You should not generate key names in your script (i.e. call SET with "item:" .. id as a keyname) but rather use the KEYS input array to declare any keys involved a priori.
Secondly, instead of passing the stringified string with KEYS, use the ARGV input array.
Thirdly, you can do item["data"] = json.decode(ARGV[1]) to avoid the double encoding.
Lastly, perhaps you should learn about Redis' Hash data type - it may be more suitable to your needs.

cant set Index ObjectChoiceField (load slow json)

I have a select that I get Json post with http, but I try to sets initially selected index but there is nothing in the list do not select anything. because the json is great.
public AppMainScreen() {
loadLists();
MySelect = new ObjectChoiceField( "Select: ", new Object[0], 3 );
VerticalFieldManager vfm = new VerticalFieldManager(Manager.VERTICAL_SCROLL);
vfm.add(MySelect);
add(vfm);
}
This statement appears wrong to me:
new ObjectChoiceField( "Select: ", new Object[0],3);
The second parameter to this constructor is supposed to be an array of objects whose .toString() method will be used to populate the choices. In this case, you have given it a 0 length array, i.e. no Objects. So there is nothing to choose. And then you have asked it to automatically select the 3rd item, and of course there is no 3rd item.
You should correct the code to actually supply an object array.
One option to make it easy is have your JSON load actually create a String array with one entry per selectable item. Then you use the index selected to identify the chosen item.