How to write Redis 'mset' programmatically in node.js? - redis

I have multiple keys and values which I can set to Redis by calling 'set' method multiple times which just takes (key, value).
How can I do the same with Redis 'mset' command and pass those key,value pairs?

using ioredis:
client.MSET('key1', 'value1', 'key2', 'value2');
using node-redis:
client.MSET({ 'key1': 'value1', 'key2': 'value2' });
client.MSET(['key1', 'value1', 'key2', 'value2']);
client.MSET([['key1', 'value1'], ['key2', 'value2']]);

Related

Possible to query for data in multiple keys in the same query?

I'm trying to lookup some data in my database using a string, but utilizing multiple json keys to check in.
I know you can lookup using a single key in this case 'name'
SELECT *
FROM products_product
WHERE data->>'name' IN ('Value 1', 'Value 2')
My issue is that i have two types of json values being saved and therefore need to check both 'name' and 'title'
As an example to simplify it:
{
"name": "Value 1"
}
while the second maybe looking like this:
{
"title": "Value 2"
}
How can i do a single query check both 'name' and 'title' for the values i got?
I was expecting maybe to be able to do something like
SELECT *
FROM products_product
WHERE data->>('name', 'title') IN ('Value 1', 'Value 2')
But its not possible!
Would want to avoid having to do multiple queries as i know the keys the data can be placed in and got them as a list or tuple (whatever is needed)
So my final question is:
How can i query the database to check multiple fields (if they exist) for the values i have defined?
I'm expecting both the examples to be returned in a single query and not just one of them
You can use an OR
SELECT *
FROM products_product
WHERE data->>'name' IN ('Value 1', 'Value 2')
OR data->>'title' IN ('Value 1', 'Value 2')
You can slightly simplify this, by only specifying the values once:
with input (val) as (
values ('Value1'), ('Value2') --<< note the parentheses!
)
SELECT *
FROM products_product
WHERE data->>'name' IN (select val from input)
OR data->>'title' IN (select val from input)
You don't say what version you are using. You can do this with json path in postgres 12. The syntax is a bit obtuse, but it's possible:
SELECT * FROM products_product
WHERE jsonb_path_exists(data,
'strict $.keyvalue() ? ((#.value == "Value 1" || #.value == "Value 2") && (#.key == "name" || #.key == "title"))');
This will search every key/value combo at the root of your object and look for keys equalling name or title and values equalling Value 1 or Value 2.

How to generate JSON in PostgreSQL with conditional keys

I am generating JSON using a query that looks like this
SELECT
json_build_object(
'key1', t1.field1,
'key2', t1.field2,
'key3', t1.field3
)
FROM table1 as t1
WHERE ...
and I get results that look like this
{"key1": 123, "key2": "some string", "key3": 100}
or like this
{"key1": 123, "key2": "some string", "key3": null}
What I need is a way to make the second example drop the whole key instead of including the null value. That is, I want to somehow omit key3 when the value in field3 is null. And end up with this JSON
{"key1": 123, "key2": "some string"}
How do I go about this? I am running PostgreSQL 9.4, so some JSON operations are not available to me.
You can use json_object_agg:
SELECT
(SELECT json_object_agg(name, value)
FROM (VALUES
('key1', to_json(t1.field1)),
('key2', to_json(t1.field2)),
('key3', to_json(t1.field3))
) AS props(name, value)
WHERE value IS NOT NULL
) AS json
FROM table1 as t1
WHERE ...

Set table in a value in Redis

I have a key which has fields and values. All the fields have string values.
One of these fields I want it to be a table or set or list (meaning holding multiple values). This field is called zonetable
I only know how to use hset but as far as I know it cannot do what I want. I would like to do something like that
hmset L0001:ad65ed38-66b0-46b4-955c-9ff4304e5c1a field1 blabla field2 blibli zonetable [1,2,3,4]
Key : L0001:ad65ed38-66b0-46b4-955c-9ff4304e5c1a
field1: "string value"
field2: "string value"
zonetable: [1,2,3,4] ---- the table
Maybe you can make use of Json. use json serialize your table (list or something) into a json string, then use hset to save it into your redis.
When you want to retrieve it, first get it from redis and then deserialize it from json to list.
If you use python, you can do it like this:
table = json.dumps(zonetable)
redis.hset(Key, 'zonetable', table)
when you want to retrieve it :
table = redis.hget(Key, 'zonetable')
zonetable = json.loads(table)
As you say, you use the native command, you can also do this.
first, convert your zonetable to json string using python interpreter
>>> import json
>>> table = [1,2,3,4]
>>> json.dumps(table)
'[1, 2, 3, 4]'
then use this in redis-cli
hmset L0001:ad65ed38-66b0-46b4-955c-9ff4304e5c1a field1 blabla field2 blibli zonetable '[1,2,3,4]'
Yes, one more thing I want to say, if you know the rule of how to convert object to json, you could do it by yourself.

Pig: How to join data on a key in a nested bag

I'm simply trying to merge in the values from data2 to data1 on the 'value1'/'value2' keys seen in both data1 and data2 (note the nested structure of
Easy right? In object oriented code it's a nested for loop. But in Pig it feels like solving a rubix cube.
data1 = 'item1' 111 { ('thing1', 222, {('value1'),('value2')}) }
data2 = 'value1' 'result1'
'value2' 'result2'
A = load 'data6' as ( item:chararray, d:int, things:bag{(thing:chararray, d1:int, values:bag{(v:chararray)})} );
B = load 'data7' as ( v:chararray, r:chararray );
expected: 'item1', 111, {('thing1', 222, {('value1','result1'), ('value2','result2')})}
^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
For the curious: data1 comes from an object oriented datastore, which explains the double nesting (simple object oriented format).
It sounds like you basically just want to do a join (unclear from the question if this should be INNER, LEFT, RIGHT, or FULL. I think #SNeumann basically has the write answer, but I'll add some code to make it clearer.
Assuming the data looks like:
data1 = 'item1' 111 { ('thing1', 222, {('value1'),('value2')}) }
...
data2 = 'value1' 'result1'
'value2' 'result2'
...
I'd do something like (untested):
A = load 'data6' as ( item:chararray, d:int, things:bag{(thing:chararray, d1:int, values:bag{(v:chararray)})} );
B = load 'data7' as ( v:chararray, r:chararray );
A_flattened = FOREACH A GENERATE item, d, things.thing AS thing; things.d1 AS d1, FLATTEN(things.values) AS value;
--This looks like:
--'item1', 111, 'thing1', 222, 'value1'
--'item1', 111, 'thing1', 222, 'value2'
A_B_joined = JOIN A_flattened BY value, B BY v;
--This looks like:
--'item1', 111, 'thing1', 222, 'value1', 'value1', 'result1'
--'item1', 111, 'thing1', 222, 'value1', 'value2', 'result2'
A_B_joined1 = FOREACH A_B_JOINED GENERATE item, d, thing, d1, A_flattened::value AS value, r AS result;
A_B_grouped = GROUP A_B_joined1 BY (value, result);
From there, rebagging however you like should be trivial.
EDIT: The above should have used '.' as the projection operator on tuples. I've switched that in. It also assumed things was a big tuple, which it isn't. It's a bag of one item. If the OP never plans to have more than one item in that bag, I'd highly recommend using a tuple instead and loading as:
A = load 'data1' as (item:chararray, d:int, things:(thing:chararray, d1:int, values:bag{(v:chararray)}));
and then using the rest of the code essentially as is (note: still untested).
If a bag is absolutely required, then the entire problem changes, and it becomes unclear what the OP wants to happen when there are multiple things objects in the bag. Bag projection is also quite a bit more complicated as noted here
I'd try to flatten the bag in A that contains values (1,2), join with B (inner, outer, whatever you're after) and then group again and project the desired structure using TOBAG, etc.

How can I use a Sequel SQL function in an insert statement?

I would like to use a SQL function when inserting a new value into a dataset. However, I keep getting TypeError: can't convert Sequel::SQL::Function into String errors. The Sequel docs explain how to select using functions, but not insert.
Ideally I would like to avoid DB.run since I am inserting dynamically and raw SQL is messy and inflexible.
This is what I'm trying to do:
INSERT INTO dataset (col1, col2, col3) VALUES ('something', 3, func(value))
This is what I have in Sequel:
x = 'something'
y = 3
func_value = Sequel.function(:func, value)
DB[:dataset].insert (:col1 => x, :col2 => y, :col3 => func_value)
Is this possible? If so, what am I missing?
Figured it out. Create a Sequel::function object, and then make it the value in your hash.
irb(main):028:0> tbl
=> #<Sequel::MySQL::Dataset: "SELECT * FROM `foo`.`bar`">
irb(main):029:0> uhex = Sequel.function(:unhex,7)
=> #<Sequel::SQL::Function #args=>[7], #f=>:unhex>
irb(main):030:0> tbl.insert_sql( {:field_name => uhex })
=> "INSERT INTO `foo`.`bar` (`field_name`) VALUES (unhex(7))"
Looks like there a few different ways syntactically of calling SQL functions in Sequel:
http://sequel.rubyforge.org/rdoc/files/doc/dataset_filtering_rdoc.html