In Postgres I have created a simple table called tags with these columns:
tag_id
tag
owner_id
In ExpressJS, this query works fine:
return pool.query(`SELECT tag_id, tag FROM tags WHERE owner_id = $1`, [ownerId]);
Now what I want to do is restrict which tags are returned via an array of tag values I'm passing in:
const tagsCsv = convertArrayToCSV(tags); // Example: "'abc','def'"
return pool.query(`SELECT tag_id, tag FROM tags WHERE owner_id = $1 AND tag IN ($2)`, [ownerId, tagsCsv]);
The code doesn't crash but it returns an empty array when I know for a fact that both abc & def are sample tags in my table.
I thus suspect something is wrong with my syntax but am not sure what. Might anyone have any ideas?
Robert
I did more searching and found this: node-postgres: how to execute "WHERE col IN (<dynamic value list>)" query?
Following the examples in there, I stopped converting the string array to a CSV string and instead did this:
const tags: Array<string> = values.tags;
return pool.query(`SELECT tag_id, tag FROM tags WHERE owner_id = $1 AND tag = ANY($2::text[])`, [ownerId, tags]);
This worked perfectly, returning the records I was expecting!
Related
I have a database with a json field which has multiple parts including one called tags, there are other entries as below but I want to return only the fields with "{"tags":{"+good":true}}".
"{"tags":{"+good":true}}"
"{"has_temps":false,"tags":{"+good":true}}"
"{"tags":{"+good":true}}"
"{"has_temps":false,"too_long":true,"too_long_as_of":"2016-02-12T12:28:28.238+00:00","tags":{"+good":true}}"
I can get part of the way there with this statement in my where clause trips.metadata->'tags'->>'+good' = 'true' but that returns all instances where tags are good and true including all entries above. I want to return entries with the specific statement "{"tags":{"+good":true}}" only. So taking out the two entries that begin has_temps.
Any thoughts on how to do this?
With jsonb column the solution is obvious:
with trips(metadata) as (
values
('{"tags":{"+good":true}}'::jsonb),
('{"has_temps":false,"tags":{"+good":true}}'),
('{"tags":{"+good":true}}'),
('{"has_temps":false,"too_long":true,"too_long_as_of":"2016-02-12T12:28:28.238+00:00","tags":{"+good":true}}')
)
select *
from trips
where metadata = '{"tags":{"+good":true}}';
metadata
-------------------------
{"tags":{"+good":true}}
{"tags":{"+good":true}}
(2 rows)
If the column's type is json then you should cast it to jsonb:
...
where metadata::jsonb = '{"tags":{"+good":true}}';
If I get you right, you can check text value of the "tags" key, like here:
select true
where '{"has_temps":false,"too_long":true,"too_long_as_of":"2016-02-12T12:28:28.238+00:00","tags":{"+good":true}}'::json->>'tags'
= '{"+good":true}'
I have a table with multiple column and I want to return a column name using another column name as search criteria. How do I achieve this in yii2?
Below is sample code, normal sql should be:
$name = SELECT type_name FROM ProductTable WHERE type_id = 1;
echo $name;
This should return the value of the column type_name where the value of the column type_id equals 1. I tried this, but it doesn't work
$type_name = ProductTable::find()->where(['type_id' =>$model->type_id]);
$type_name = Product::find(['type_name'])->where(['type_id' =>$model->type_id]);
I also tried this, but I guess it was wrong
I hope my question is clear enough and any help will he appreciated
and u could also use createCommand!
$name = \Yii::$app->getDb()->createCommand("SELECT type_name FROM ProductTable WHERE type_id=:typeId", ['typeId'=>$model->type_id])->queryAll();
For a general introduction to Yii2's ActiveRecord, see the guide: http://www.yiiframework.com/doc-2.0/guide-db-active-record.html
If you want the complete row and have a model, you're just missing a one():
Product::find()->where(['type_id' =>$model->type_id])->one();
If you do have a Model defined and just want a single value, try:
Product::find()->select('type_name')->where(['type_id' =>$model->type_id])->scalar();
Which basically generates an ActiveQuery via the model, and changes it to return only the first column in the first row of matched results.
If you do NOT have a model, you could also generate a normal query without ActiveRecord usage (http://www.yiiframework.com/doc-2.0/yii-db-query.html)
$name = (new Query())->select('type_name')
->from('ProductTable')
->where(['type_id' =>$model->type_id])
->scalar();
I assume you generated ProductTable by using Gii module.
Also, if type_id column is a primary key:
$product = ProductTable::findOne($model->type_id);
if($product !== null) { $product->typeName /*... read value ...*/}
or to get all records
$products = ProductTable::findAll($model->type_id); //match all records.
for any other column use the following syntax instead:
$product = ProductTable::findOne(['type_id' => $model->type_id]);
Use following code to get type_name
$PTable=ProductTable::find()->select('type_name')->where(['type_id' =>$model->type_id])->one();
echo $PTable->type_name;
About database
Database table for content of an Confluence page is named bodycontent and the HTML content is stored in column named body, which is a text field. Im using Postgres database. Primary key is named bodycontentid
Result I need
For each row in the table I need to find all occurence of <image> tag where src attribute starts with "http://images.mydomain.com/allImages/%" in the body column
Example
Let say that body with bodycontentid = 12345 contains following text:
<h1>Chapter 1</h1>
<image src="http://www.google.com/image/111.jpg"/>
<h1>Chapter 2</h1>
<image src="http://images.mydomain.com/allImages/222.jpg"/>
<h1>Chapter 3</h1>
<image src="http://images.mydomain.com/allImages/333.jpg"/>
Result after running this query should return:
bodycontentid: 12345
body: http://images.mydomain.com/allImages/222.jpg
bodycontentid: 12345
body: http://images.mydomain.com/allImages/333.jpg
What I have tried
Im able to find all rows that has at least one occurence of the keyword Im searching for (see below), but what I need is to get list of all keywords per row that is matching my query.
SELECT *
FROM bodycontent
WHERE body LIKE '%http://images.mydomain.com/allImages/%'
One method is to use regexp_split_to_table() and then some string manipulation:
select bc.bodycontentid,
left(rst.s, position('"' in rst.s) - 1) as domain
from bodycontent bc, lateral
regexp_split_to_table(bc.body, E'srce="') rst(s)
where rst.s like 'http://images.mydomain.com/allImages/%';
Hi have a text search input that looks for matching records in the DB and gets all the data from a table:
let's say like this:
$q = Input::get('items');
$q = "\"" . "($q)" . "\"";
$items = DB::table('my_items')->whereRaw(
'MATCH(item_name) AGAINST(? IN BOOLEAN MODE)',
array($q)
)->get();
So I get all the items in the DB from my textsearch, then I send the result as json to some script that updates my page with the items:
return Response()->json($items);
The relations are:
My_item:
public function brand(){
return $this->hasOne('App\Brand', 'id', 'brand_id');
}
Brand:
public function My_item(){
return $this->belongsToMany('App\My_item');
}
Now the problem here is that in 'my_items' table I have some data as IDs that reference foreign tables.
For example I will have a 'brand_id' that for example references a 'brands' table where I can have information regarding the brand.
So for example I could have brand_id = 3 that means 'Microsoft' in my brands table (id = 3, name = microsoft).
Now what I need to do is not only passing the brand_id to my view but also the actual information (name), in this case Microsoft so that I can put that info in the item description.
But, how can I get that information before sending with that query? Is there some sort of flag I can use in the query like $items = DB::table bla bla with foreign?
this way works, DB:: method is dropped for:
$items = My_item::with('brand')->where('item_name', 'LIKE', "%$q%")->get();
this one doesn't:
DB::table('my_items')::with('brand')->where('item_name', 'LIKE', "%$q%")->get();
First of all, you can simplify your search query to something like this:
My_item::where('item_name', 'LIKE', "%$q%")->get();
Now, assign relations the relation to your other tables in your Models. Then you can get all information using the following syntax:
My_item::with('brand')->where('item_name', 'LIKE', "%$q%")->get();
Read more about relations here: https://laravel.com/docs/5.1/eloquent-relationships
Imagine the following tables :
Tag (TagId, Label)
Post (PostId, Title, Content)
User (UserId, Name)
UserPostTag (Id, UserId, PostId, TagId)
For a Post, multiple users can add one or more Tag.
I want to get, via nHibernate, the tag list for a post, with the count of each Tag.
Exemple or result :
Tag(id1, label1), 7
Tag(id2, label2), 5
Tag(id3, label3), 2
I know how to get list of tags for a post :
IList<Tag> tagList = session.CreateCriteria<Tag>()
.Add(Subqueries.PropertyIn("TagId",
DetachedCriteria.For<UserPostTag>()
.Add(Restrictions.Eq("Post.PostId", 17))
.SetProjection(Projections.Property("Tag.TagId"))
))
.List<Tag>();
Can you please help me ?
Thanks a lot !
Sorry for my english ...
Sincerely,
Antoine
If I'm right, create the HQL query like this:
#"SELECT new Tag(tag.Id, tag.Label), count(cloud.User)
FROM UserPostTag cloud
JOIN cloud.Tag tag
WHERE cloud.Post.Id = :postId
GROUP BY tag.Id, tag.Label"
Enter this in the CreateQuery call, it works only if you have a constructor on Tag which accepts an id and a label. (Don't forget to set the postId parameter.)
This returns a list with tag and list in an array, I believe.
Update: if this does not work, you can create a new class TagCount which has a tag and a count and change the select syntax to something like the following:
SELECT new TagCount(tag.Id, tag.Label, count(cloud.User))
(Disclaimer: I did not try this.)
If I were you, I would make an extra member for the Post class, name it Tags and map it as many to many to your UserPostTag table. In this case you can use the following code to get your task done:
Make a class to retreive your results:
class TagWithCount
{
public string Label {get;set;}
public int Count {get;set;}
}
Create a query (using QueryOver):
Tag ta = null;
TagWithCount res = null;
var query = QueryOver.Of<Post>()
.JoinAlias(x=>x.Tags, ()=>ta)
.SelectList(x=>x.SelectGroup(() => ta.Label).WithAlias(() => res.Label),
.SelectCount(p=>p.Id).WithAlias(() => res.Count))
.Where(x=>x.Id == postId)
.TransformUsing(Transformers.AliasToBean<TagWithCount>());
Select the actual result:
var res = query.GetExecutableQueryOver(session).List<TagWithCount> ();
P.S.: I haven't check if the code completely correct, it is just to give an idea.