How to write a N1QL query for the below requirement - couchbase

I have the below project records.
"projectkey1" : {
"name" : "project name",
"productDetails" :{
"productKey1":"requested",
"productkey2":"requested"
}
"type" : "project"
}
Now each product is stored as below are
"productKey1"(key) : {"description" : "product1" , "type" : "product"}
We have multiple project records but what products are associated with the project is shown in the above key as key value pairs with the actual product key as a key in the project record. Also there is no limit on how many product keys a project can have. Given these requirements how can i write a N1ql that will give the projectname and the product description in the same json
Some thing like
[{
"name" : "project name",
"product list" : ["product description1", "product description2"]
},
{
"name" : "project name2",
"product list" : ["product description3", "product description4"]
}
]

CREATE INDEX ix1 ON default(name ) WHERE type = "project";
SELECT p.name,
(SELECT RAW pd.description
FROM default AS pd USE KEYS OBJECT_NAMES(p.productDetails)
WHERE pd.type = "product"
) AS productList
FROM default AS p
WHERE p.type = "project"
AND p.name IS NOT NULL;

Related

FastAPI 422 Unprocessable Entity - how to update many rows at once?

I want to update all rows in the values table that meet a condition based on a customer id and a group. I used the join statement to select all products that belong to the specific group. The table is set as
class Values(Base):
__tablename__ = 'values'
customer_id = Column(Integer, ForeignKey('customer.customer_id'), primary_key=True, ullable=False)
product_id = Column(Integer, ForeignKey('product.product_id'), primary_key = True, nullable= False)
quantity = Column(Numeric)
#router.put('/{customer_id}/{group}')
def update_values(customer_id: int, group:str, updated: schemas.Quantity, db: Session = Depends(get_db)):
sub_query = db.query(models.Values, models.Product.group).join(models.Product, models.Product.product_id == models.Values.product_id).filter(models.Values.customer_id==customer_id, models.Product.group==group).subquery()
main_query = db.query(models.Values).filter(models.Values.product_id.in_(sub_query))
main_query.update({models.Values.quantity: updated.item_value}, synchronize_session=False)
db.commit()
return main_query.all()
My schema is
class Quantity(BaseModel):
item_value: float
I get the error message 422 Unprocessable Entity.
{
"detail": [
{
"loc": [
"path",
"product_id"
],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
}
Could someone point out what I am doing wrong?

How to use an operator in where clause with an optional include?

I have the following Model:
AuthorModel.hasMany(BookModel);
BookModel.belongsTo(AuthorModel);
Some authors have no books.
I want to select an author whose name or title of one of his books matches the search string.
I can achieve this with the following statement, but only for authors with books in their BookModel
Author.findOne({
include: [{
model: Book,
where: {
[Op.or]: [
{'$author.name$': 'search string'},
{ title: 'search string'}
]
},
}]
})
This gives me more or less the following mysql query:
SELECT
`author`.`name`,
`book`.`title`
FROM `author` INNER JOIN `book`
ON `author`.`id` = `book`.`authorId`
AND ( `author`.`name` = 'search string' OR `book`.`title` = 'search string');
The problem here is, if an author has no books, then the result is empty. Even if there is an author that matches the search criteria.
I tried to set the include to required: false, which gives a left outer join. In that case, I get some not matching results. The where clause is omitted.
How do I have to change my sequelize query, or what would be the proper mysql query?
The MySql query should probably be something like
SELECT
`author`.`name`,
`book`.`title`
FROM `author` LEFT JOIN `book`
ON `author`.`id` = `book`.`authorId`
WHERE ( `author`.`name` = 'search string' OR `book`.`title` = 'search string')
Note how here filtering condition is in WHERE rather than part of JOIN ... ON clause
Basing on the example at Top level where with eagerly loaded models you squizzle query should probably be something like
Author.findOne({
where: {
[Op.or]: [
{'$author.name$': 'search string'},
{ '$Book.title$': 'search string'}
]
},
include: [{
model: Book,
required: false
}]})

mysql search child & parent table fields with sequelize in nodejs

In my Node application we have used Sequelize to connect with mysql
Have two table User & UserOption
User table have following fields
user_id(pk)
user_email
UserOption table have following fields
option_id(pk)
user_id(fk)
first_name
I need to list all user by search text in user_email & first_name
Is there any option to search both parent & child table fields in Sequelize?
UPDATE
User table
user_id user_email
1 text#text.com
2 anything#anything.com
3 jhon#smthng.com
UserOption table
option_id user_id first_name
1 1 jhon
2 2 smith
3 3 david
If I search for "jhon", the result will be both user with id 1 and 2
You need to include model UserOption in lookup on model User. This generates a JOIN clause with condition UserOption.user_id = User.user_id, as well as adds specified WHERE clause to perform text lookup on user_email and first_name columns of both tables
User.findAll({
where: {
user_email: { $like: '%text%' }
},
include: [
{
model: UserOption,
where: {
first_name: { $like: '%text%' }
},
attributes: []
}
]
}).then((users) => {
// result
});
EDIT
Basing on your updated question, I think that you can try using sequelize.literal method, but, according to the documentation:
Creates a object representing a literal, i.e. something that will not be escaped.
So it is necessary to escape desired values by yourself
let escValue = sequelize.escape(lookupText);
User.findAll({
where: {
$or: [
{ email: { $like: '%' + lookupText + '%' },
{ id: { $in: sequelize.literal(`(SELECT uo.user_id FROM user_options uo WHERE uo.first_name LIKE CONCAT('%', ${escValue}, '%'))`) }
]
}
}).then((users) => {
// result...
});
It would generate a query which selects users from users table where email LIKE '%text%' or where users.id is in specified query result.
I am very curious if this satisfies your needs, waiting for feedback.

Mysql Join rows from multiple tables

I am asking here because what english words i need to search for this what i want to do.
I can solve this with multiple queries then join arrays with for and foreach loops but why to do it if there is smarter way.
My query now looks like:
SELECT p.* , pi.path, pv.videoid
FROM products p
JOIN productimage pi ON (p.id = pi.product)
JOIN productvideo pv ON (p.id = pv.product)
WHERE p.id=:id
my tables look like
product:
|---id---|---name----|---desc---|---price---|---active----|
|---1----|---somet---|---dsa----|---456-----|---1/0-------|
|---2----|---somet2--|---ddsasa-|---44556---|---1/0-------|
product video:
|----id----|---product----|----videoid-------|
|----4-----|---1----------|-----youtubeid----|
|----4-----|---1----------|--secondyoutubeid-|
and same as video for images, and i want to make same for files
result like this to make it easy
//result of $stmt->fetchAll(PDO::FETCH_ASSOC);
$arr = array(
0 => array(
"id" => "1",
"name" => "hello world",
"category" => "3",
"videoid" => array("oneyoutubeid", "secondid", "thirdid"), //videos that is for this product
"path" => array("imagepathofproduct", "secondimageofproduct"),
"active" => "1"
),
1 => array(
"id" => "2",
"name" => "hello world product 2",
"category" => "4",
"videoid" => array("oneyoutubeid", "secondid", "thirdid"), //videos that is for this product
"path" => array("imagepathofproduct", "secondimageofproduct"),
"active" => "1"
),
);
to use it like this: return $stmt->fetchAll(PDO::FETCH_ASSOC); and start foreach for displaying data.
thankyou very much
solved by concat and i will explode it into array.
but still waiting for more smart solutions.
Solution:
SELECT p.* , GROUP_CONCAT(DISTINCT path ORDER BY pi.id) AS images, GROUP_CONCAT(DISTINCT videoid ORDER BY pi.id) AS videos FROM products p JOIN productimage pi ON (p.id = pi.product) JOIN productvideo pv ON (p.id = pv.product) WHERE p.id=1
Home it will helpt to somebody

Can you make multilevel arrays with one query?

Is it possible to make a multilevel array using a mysql query? E.g. if I want to get 4 pictures for each product?
[1] => Array( 'name' => 'Product 1', 'picture' => array('picture1','picture2','picture3','picture4') )
[2] => Array( 'name' => 'Product 2', 'picture' => array('picture5','picture6','picture7','picture8') )
Or do I need to make a foreach to loop through the products and then in the foreach make a mysql query to get each products pictures?
EDIT:
My structure is:
P_Attributes
--------
id, int(15)
name, varchar(256)
P_AttributeValues
--------
id, int(15)
value, varchar(256)
attribute_id, int(15) [NOTE: This is connected to P_Attributes.id]
Then I want to get ALL P_AttributeValues to a P_Attribute row - and get it in ONE query. Is that possible?
EDIT 2:
With the query made by the accepted answers author I made it work with this PHP-code:
$attributevalues = $auctionClass->get_rows($id);
$attr_val = array();
foreach($attributevalues as $k => $v){
$attr_val[$v->AID]['attr_name'] = $v->AName;
$attr_val[$v->AID]['parameters'][] = array('attr_value_name' => $v->name, 'id' => $v->id);
}
Here is a good article on doing this type of query:
http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/
You might be able to adjust their examples to fit your needs.
If you just use a normal JOIN query and order it, you can get rows coming out of the records that can be formed in to the necessary hierarchical structure.
SELECT pa.id AS product_id, pa.name , pav.id AS product_attr_id, pav.value
FROM P_Attributes pa JOIN P_AttributeValues pav ON pav.attribute_id = pa.id
ORDER BY pa.id ASC, pav.id ASC
This will generate rows like this:
product_id, name, product_attr_id, value
1, "Product 1", 1, "picture1"
1, "Product 1", 2, "picture2"
1, "Product 1", 3, "picture3"
1, "Product 1", 4, "picture4"
2, "Product 2", 5, "picture5"
2, "Product 2", 6, "picture6"
2, "Product 2", 7, "picture7"
2, "Product 2", 8, "picture8"
No idea what MySQL extension you are using, presumably PHP as I mentioned it and you didn't correct me. If you fetch the associative array per record returned, which will be, per record, in this form:
array('product_id' => 1, 'name' => "Product 1",
'product_attr_id' => 1, 'value' => "picture1");
If you have a main data array called $products, you can produce it by just putting this code in the loop, assuming the record is called $productRec and filled in the loop before this.
if (!array_key_exists($productRec['product_id'], $products)) {
$products[$productRec['product_id']] = array('name' => $productRec['name'],
'picture' => array());
}
$products[$productRec['product_id']]['picture'][$productRec['product_attr_id']] =
$productRec['value'];
Using the IDs for the keys should be alright, presuming that they are primary keys with no duplicates. Will aid look up that way, rather than losing that data.
Depending on your table structure, you may be able to pull rows that have everything you're looking for, and then code the creation of the array from that row.