This SQL query:
SELECT name
FROM user
WHERE user.provider = "google" or user.email="email#example.com"
have equivalent mongodb query:
db.user.find({
"$or": [{
"user.provider": "google"
}, {
"user.email": "email#example.com"
}]
}, {
"name": 1
});
How about this one?
SELECT name
FROM user
WHERE (user.provider = "google" and user.id="1") or user.email="email#example.com"
What is the equivalent of the above SQL to mongo? Is it possible to have combined and & or in mongo?
Yes, you can combine them. You should be able to do:
"$or":[
{"$and": [{"user.provider": "google"}, {"user.id": "1"}] },
{ "user.email" : "email#example.com" }
]
Related
I have a sequelize query that looks like
const deliveriesToCancel = await Model.ShipperContract.findByPk(organizationId, {
include: [
{
model: Model.Order,
as: organizationId,
include: [
{
model: Model.Delivery,
as: "deliveries",
where: {
state: {
[Op.not]: "DELIVERED" || "CANCELED_BYL" || "CANCELED_BY_SHIPPER"
}
}
},
],
},
],
});
Is it possible to query on Delivery table with 3 possible choices for state column? or in this case, WHERE !== those 3 values?
How can I write taht in seqeulize?
If you want to select the deliveries where "state" isn't any of "DELIVERED", "CANCELED_BYL", or "CANCELED_BY_SHIPPER", you can use:
where: {
state: {
[Op.notIn]: ["DELIVERED", "CANCELED_BYL", "CANCELED_BY_SHIPPER"]
}
}
Note:
WHERE NOT IN can be slow. If your dataset is huge and your query is slow, consider looking into modifying it to an exists. Docs, Docs
I have two documents on mongodb, these are percentages and items. I'm good at SQL, I can write PLSql query as follows but i can not convert to mongodb query. Because my mongodb level of knowledge is at the beginning. Actually I know I have to use $gt for the and condition. But I don't know how I can say not exists or union keyword for mongodb. How can I write mongodb query? which keywords should i search for?
select p.*, "to_top" as list
from percentages p
where p.percentage > 5
and p.updatetime > sysdate - 1/24
and not exists (select 1
from items i
where i.id = p.p_id
and i.seller = p.seller)
order by p.percentage desc
union
select p2.*, "to_bottom" as list
from percentages p2
where p2.percentage > 5
and p2.updatetime > sysdate - 1/24
and exists (select 1
from items i2
where i2.id = p2.p_id
and i2.seller = p2.seller)
order by p2.percentage desc
There is no UNION for MongoDB. Luckely, each query is performed on the same collection and have very close condition, so we can implement "Mongo way" query.
Explanation
Normally, alsmost all complex SQL queries are done with the MongoDB aggregation framework.
We filter document by percentage / updatetime. Explanation why we need to use $expr
SQL JOIN / Subquery is done with the $lookup operator.
SQL SYSDATE in MongoDB way can be NOW or CLUSTER_TIME variable.
db.percentages.aggregate([
{
$match: {
percentage: { $gt: 5 },
$expr: {
$gt: [
"$updatetime",
{
$subtract: [
ISODate("2020-06-14T13:00:00Z"), //Change to $$NOW or $$CLUSTER_TIME
3600000
]
}
]
}
}
},
{
$lookup: {
from: "items",
let: {
p_id: "$p_id",
seller: "$seller"
},
pipeline: [
{
$match: {
$expr: {
$and: [
{
$eq: [ "$$p_id", "$id"]
},
{
$eq: [ "$$seller", "$seller"]
}
]
}
}
},
{
$limit: 1
}
],
as: "items"
}
},
{
$addFields: {
list: {
$cond: [
{
$eq: [{$size: "$items"}, 0]
},
"$to_top",
"$to_bottom"
]
},
items: "$$REMOVE"
}
},
{
$sort: { percentage: -1 }
}
])
MongoPlayground
Note: The MongoDB aggregation has the $facet operator that allows to perform different queries on the same collection.
SCHEMA:
db.percentages.aggregate([
{$facet:{
q1:[...],
q2:[...],
}},
//We apply "UNION" the result documents for each pipeline into single array
{$project:{
data:{$concatArrays:["$q1","$q2"]}
}},
//Flatten array into single object
{$unwind:"$data"}
//Replace top-level document
{$replaceWith:"$data"}
])
MongoPlayground
why you don't import your mangoDB data into oracle and use sql(that is more easy and powerful than mango.)
How can I return all documents which have parameter.code = "123", given this document structure, using CosmosDB SQL query? Is it necessary to use a UDF? (If so, how?)
{
"batch_id": "abc",
"samples": [
{
"sample_id": "123",
"tests": [
{
"parameter": {
"code": "123", // <- target
}
}
]
}
]
}
No need to use UDF(User Defined Function),just use cosmos db query sql with double JOIN.
SQL:
SELECT c.batch_id FROM c
join samples in c.samples
join tests in samples.tests
where tests.parameter.code = "123"
Output:
Goal:
This sql and its result should be the same result from mongoDB's query code.
In order words, same result but for mongoDB.
Problem:
How to you make a lookup connection in relation to People and Role in Mongo DB's query code?
Info:
I'm new in mongo DB
SQL code
SELECT
a.*,
'.' AS '.',
b.*,
'.' AS '.',
c.*
FROM
[db1].[dbo].[People_Course_Grade] a
INNER JOIN [db1].[dbo].[People] b on a.PeopleId = b.PeopleId
INNER JOIN [db1].[dbo].[Role] c on b.RoleId = c.RoleId
Json data:
Role:
[{"RoleId":1,"Name":"Student"},{"RoleId":2,"Name":"Teacher"}]
People_Course_Grade:
[{"People_Course_GradeId":1,"PeopleId":1,"CourseId":1},
{"People_Course_GradeId":2,"PeopleId":2,"CourseId":1},
{"People_Course_GradeId":3,"PeopleId":3,"CourseId":2},
{"People_Course_GradeId":4,"PeopleId":1,"CourseId":2}]
Course:
[{"CourseId":1,"Name":"Java"},{"CourseId":2,"Name":"Java II"},
{"CourseId":3,"Name":"Statistik 1"}]
db.People_Course_Grade.aggregate([
{
$lookup:{
from: "People",
localField: "people_id",
foreignField: "_id",
as: "people"
}
},
{ $unwind:"$people" },
{
$project:{
course_id : 1,
people_id : 1,
// grade_id : 1,
Name : "$people.Name",
}
}
]);
You need to start with double $lookup since you have three collections. Then you can use $arrayElemAt to always get single element from lookup's result. To flatten your structure you can use $replaceRoot with $mergeObjects (promotes all the fields from people and course to root level.
db.People_Course_Grade.aggregate([
{
$lookup:{
from: "Role",
localField: "PeopleId",
foreignField: "RoleId",
as: "people"
}
},
{
$lookup:{
from: "Course",
localField: "CourseId",
foreignField: "CourseId",
as: "course"
}
},
{
$replaceRoot: {
newRoot: {
$mergeObjects: [
"$$ROOT",
{ $arrayElemAt: [ "$people", 0 ] },
{ $arrayElemAt: [ "$course", 0 ] },
]
}
}
},
{
$project: {
people: 0,
course: 0
}
}
])
Mongo Playground
$arrayElemAt can always be replaced with $unwind like you tried. You also have a naming conflict on name field so probably you need to run $project to rename one of those fields - otherwise you'll get only one of them in final result.
My team started to use MongoDB now and wanna migrate some sql to Mongo.
For example, I have an order table and has the fields price and quanty.I want to query the price*quanty greater than 100. sql is like below
select * from Order where price * quanty > 100;
How to use "price * quanty" this kind query in Mongo?
Thanks.
You can do this by using the $expr operator to use aggregation expressions within your query:
db.orders.find({
$expr: {
$gt: [
{ $multiply: ["$price", "$quantity"] },
100
]
}
})
As JohnnyHK points out you can use $expr, but as an alternative you can also use aggregation to first create a new field that is the product of two other fields:
db.orders.aggregate([
{ $set: { product: { $multiply: [ "$price", "$quantity" ] } } }
])
Note: $set is new in 4.2 and just an alias for $addFields
Then add a $match stage that only matches documents with the new product field meeting your condition:
db.orders.aggregate([
{ $set: { product: { $multiply: [ "$price", "$quantity" ] } } },
{ $match: { product: { $gt: 100 } } }
])