Laravel,使用 JSON_EXTRACT 和 CONCAT_WS 的搜索查询
Laravel, search query with JSON_EXTRACT and CONCAT_WS
我正在尝试在包含 JSON 个对象的 table 中执行搜索,但我无法弄清楚如何使其与 CONCAT_WS 一起使用以便通过以下方式进行搜索一次多个单词,在本例中,first_name 和姓氏的组合。
当使用单个词(first_name、last_name、电子邮件或 phone)进行搜索时,查询运行良好,但 return first_name 和 last_name 都发送到后端时的任何内容。
Model::whereRaw('
JSON_EXTRACT(data, "$.start") >= ?
AND
JSON_EXTRACT(data, "$.personal") = ?
AND
(
LOWER(JSON_EXTRACT(data, "$.user.first_name")) LIKE ?
OR
LOWER(JSON_EXTRACT(data, "$.user.last_name")) LIKE ?
OR
LOWER(JSON_EXTRACT(data, "$.user.email")) LIKE ?
OR
LOWER(JSON_EXTRACT(data, "$.user.phone")) LIKE ?
OR
CONCAT_WS(" ",LOWER(JSON_EXTRACT(data, "$.user.first_name")),LOWER(JSON_EXTRACT(data, "$.user.last_name"))) LIKE ?
)
', [
Carbon::now(),
0,
'"%' . trim(strtolower($request->searchQuery)) . '%"',
'"%' . trim(strtolower($request->searchQuery)) . '%"',
'"%' . trim(strtolower($request->searchQuery)) . '%"',
'"%' . trim(strtolower($request->searchQuery)) . '%"',
'"%' . trim(strtolower($request->searchQuery)) . '%"',
])
->orderByRaw('JSON_EXTRACT(data, "$.start") ASC')
->selectRaw('table.*, true AS future')
->get();
数据结构:
[
{
"id": 1,
"data": {
"id": 1,
"user": {
"id": 1,
"email": "email1@email.com",
"phone": "(000) 000-0000",
"last_name": "John",
"first_name": "Snow",
},
"start": "2022-03-24 17:00:00",
"personal": 0
}
},
{
"id": 2,
"data": {
"id": 2,
"user": {
"id": 2,
"email": "email2@email.com",
"phone": "(000) 000-0000",
"last_name": "Some",
"first_name": "Name",
},
"start": "2022-03-24 17:00:00",
"personal": 0
}
},
{
"id": 3,
"data": {
"id": 3,
"user": {
"id": 3,
"email": "email3@email.com",
"phone": "(000) 000-0000",
"last_name": "Other",
"first_name": "Name",
},
"start": "2022-03-24 17:00:00",
"personal": 0
}
}
]
您需要编辑
- 将
CONCAT_WS()
替换为CONCAT()
- 在
JSON_EXTRACT()
的结果上使用 JSON_UNQUOTE()
,然后再合并
所以这一行
CONCAT_WS(" ",LOWER(JSON_EXTRACT(data, "$.user.first_name")),LOWER(JSON_EXTRACT(data, "$.user.last_name")))
需要对此进行更改
CONCAT(
LOWER(JSON_UNQUOTE(JSON_EXTRACT(data,"$.user.first_name"))),
LOWER(JSON_UNQUOTE(JSON_EXTRACT(data, "$.user.last_name")))
)
理由
问题是由于
- 使用
trim()
方法删除单词之间的空格,同时用空格连接 firstname
和 lastname
- 还有
JSON_EXTRACT()
returns 带双引号的值,当你在一个单词上使用 like 时不会引起问题,但是当添加两个单词时,引号将存在于中间,并且条件将是错误的,所以我使用 JSON_UNQUOTE
到 trim 它的引号
因此您将得到以下查询
SELECT * FROM `table_name` WHERE JSON_EXTRACT(data, "$.start") >= '2022-03-24 03:09:08'
AND
JSON_EXTRACT(data, "$.personal") = 0
AND
(
LOWER(JSON_EXTRACT(data, "$.user.first_name")) LIKE "%snowjohn%"
OR
LOWER(JSON_EXTRACT(data, "$.user.last_name")) LIKE "%snowjohn%"
OR
LOWER(JSON_EXTRACT(data, "$.user.email")) LIKE "%snowjohn%"
OR
LOWER(JSON_EXTRACT(data, "$.user.phone")) LIKE "%snowjohn%"
OR
CONCAT(LOWER(JSON_UNQUOTE(JSON_EXTRACT(data, "$.user.first_name"))),LOWER(JSON_UNQUOTE(JSON_EXTRACT(data, "$.user.last_name")))) LIKE "%snowjohn%"
);
所以,在 Omar 的帮助下,这就是我的问题的解决方案!
Model::whereRaw('
JSON_EXTRACT(data, "$.start") >= ?
AND
JSON_EXTRACT(data, "$.personal") = ?
AND
(
LOWER(JSON_EXTRACT(data, "$.user.first_name")) LIKE ?
OR
LOWER(JSON_EXTRACT(data, "$.user.last_name")) LIKE ?
OR
LOWER(JSON_EXTRACT(data, "$.user.email")) LIKE ?
OR
LOWER(JSON_EXTRACT(data, "$.user.phone")) LIKE ?
OR
CONCAT_WS(" ",
LOWER(
JSON_UNQUOTE(
JSON_EXTRACT(data, "$.user.first_name")
)
),
LOWER(
JSON_UNQUOTE(
JSON_EXTRACT(data, "$.user.last_name")
)
)
) LIKE ?
)
', [
Carbon::now(),
0,
'"%' . trim(strtolower($request->searchQuery)) . '%"',
'"%' . trim(strtolower($request->searchQuery)) . '%"',
'"%' . trim(strtolower($request->searchQuery)) . '%"',
'"%' . trim(strtolower($request->searchQuery)) . '%"',
'%' . trim(strtolower($request->searchQuery)) . '%',
])
->orderByRaw('JSON_EXTRACT(data, "$.start") ASC')
->selectRaw('table.*, true AS future')
->get();
我正在尝试在包含 JSON 个对象的 table 中执行搜索,但我无法弄清楚如何使其与 CONCAT_WS 一起使用以便通过以下方式进行搜索一次多个单词,在本例中,first_name 和姓氏的组合。
当使用单个词(first_name、last_name、电子邮件或 phone)进行搜索时,查询运行良好,但 return first_name 和 last_name 都发送到后端时的任何内容。
Model::whereRaw('
JSON_EXTRACT(data, "$.start") >= ?
AND
JSON_EXTRACT(data, "$.personal") = ?
AND
(
LOWER(JSON_EXTRACT(data, "$.user.first_name")) LIKE ?
OR
LOWER(JSON_EXTRACT(data, "$.user.last_name")) LIKE ?
OR
LOWER(JSON_EXTRACT(data, "$.user.email")) LIKE ?
OR
LOWER(JSON_EXTRACT(data, "$.user.phone")) LIKE ?
OR
CONCAT_WS(" ",LOWER(JSON_EXTRACT(data, "$.user.first_name")),LOWER(JSON_EXTRACT(data, "$.user.last_name"))) LIKE ?
)
', [
Carbon::now(),
0,
'"%' . trim(strtolower($request->searchQuery)) . '%"',
'"%' . trim(strtolower($request->searchQuery)) . '%"',
'"%' . trim(strtolower($request->searchQuery)) . '%"',
'"%' . trim(strtolower($request->searchQuery)) . '%"',
'"%' . trim(strtolower($request->searchQuery)) . '%"',
])
->orderByRaw('JSON_EXTRACT(data, "$.start") ASC')
->selectRaw('table.*, true AS future')
->get();
数据结构:
[
{
"id": 1,
"data": {
"id": 1,
"user": {
"id": 1,
"email": "email1@email.com",
"phone": "(000) 000-0000",
"last_name": "John",
"first_name": "Snow",
},
"start": "2022-03-24 17:00:00",
"personal": 0
}
},
{
"id": 2,
"data": {
"id": 2,
"user": {
"id": 2,
"email": "email2@email.com",
"phone": "(000) 000-0000",
"last_name": "Some",
"first_name": "Name",
},
"start": "2022-03-24 17:00:00",
"personal": 0
}
},
{
"id": 3,
"data": {
"id": 3,
"user": {
"id": 3,
"email": "email3@email.com",
"phone": "(000) 000-0000",
"last_name": "Other",
"first_name": "Name",
},
"start": "2022-03-24 17:00:00",
"personal": 0
}
}
]
您需要编辑
- 将
CONCAT_WS()
替换为CONCAT()
- 在
JSON_EXTRACT()
的结果上使用JSON_UNQUOTE()
,然后再合并
所以这一行
CONCAT_WS(" ",LOWER(JSON_EXTRACT(data, "$.user.first_name")),LOWER(JSON_EXTRACT(data, "$.user.last_name")))
需要对此进行更改
CONCAT(
LOWER(JSON_UNQUOTE(JSON_EXTRACT(data,"$.user.first_name"))),
LOWER(JSON_UNQUOTE(JSON_EXTRACT(data, "$.user.last_name")))
)
理由 问题是由于
- 使用
trim()
方法删除单词之间的空格,同时用空格连接firstname
和lastname
- 还有
JSON_EXTRACT()
returns 带双引号的值,当你在一个单词上使用 like 时不会引起问题,但是当添加两个单词时,引号将存在于中间,并且条件将是错误的,所以我使用JSON_UNQUOTE
到 trim 它的引号
因此您将得到以下查询
SELECT * FROM `table_name` WHERE JSON_EXTRACT(data, "$.start") >= '2022-03-24 03:09:08'
AND
JSON_EXTRACT(data, "$.personal") = 0
AND
(
LOWER(JSON_EXTRACT(data, "$.user.first_name")) LIKE "%snowjohn%"
OR
LOWER(JSON_EXTRACT(data, "$.user.last_name")) LIKE "%snowjohn%"
OR
LOWER(JSON_EXTRACT(data, "$.user.email")) LIKE "%snowjohn%"
OR
LOWER(JSON_EXTRACT(data, "$.user.phone")) LIKE "%snowjohn%"
OR
CONCAT(LOWER(JSON_UNQUOTE(JSON_EXTRACT(data, "$.user.first_name"))),LOWER(JSON_UNQUOTE(JSON_EXTRACT(data, "$.user.last_name")))) LIKE "%snowjohn%"
);
所以,在 Omar 的帮助下,这就是我的问题的解决方案!
Model::whereRaw('
JSON_EXTRACT(data, "$.start") >= ?
AND
JSON_EXTRACT(data, "$.personal") = ?
AND
(
LOWER(JSON_EXTRACT(data, "$.user.first_name")) LIKE ?
OR
LOWER(JSON_EXTRACT(data, "$.user.last_name")) LIKE ?
OR
LOWER(JSON_EXTRACT(data, "$.user.email")) LIKE ?
OR
LOWER(JSON_EXTRACT(data, "$.user.phone")) LIKE ?
OR
CONCAT_WS(" ",
LOWER(
JSON_UNQUOTE(
JSON_EXTRACT(data, "$.user.first_name")
)
),
LOWER(
JSON_UNQUOTE(
JSON_EXTRACT(data, "$.user.last_name")
)
)
) LIKE ?
)
', [
Carbon::now(),
0,
'"%' . trim(strtolower($request->searchQuery)) . '%"',
'"%' . trim(strtolower($request->searchQuery)) . '%"',
'"%' . trim(strtolower($request->searchQuery)) . '%"',
'"%' . trim(strtolower($request->searchQuery)) . '%"',
'%' . trim(strtolower($request->searchQuery)) . '%',
])
->orderByRaw('JSON_EXTRACT(data, "$.start") ASC')
->selectRaw('table.*, true AS future')
->get();