how can I write this mysql query in elasticsearch ?
SELECT *,count(products.store_id)
FROM stores
INNER JOIN products
ON stores.store_id=products.store_id
group by stores.store_id;
Elasticsearch is not exactly a database, it's a search engine and hence it supports very limited JOIN operations (parent-child queries).
If you want to execute the above query then you will have to rework the schema and try to have the data in one index (doesn't matter even if it's not in 2NF/3NF). Maybe you can index store_id along with each product document.
Now, coming back to the query, if you want to execure the above query on let's say one index then you can do it using TERMS aggregation. It will give you count of products grouped by store id, the request would look like this:
$ curl -XPOST 'http://localhost:9200/products/_search?search_type=count' -d '{
"query" : {
"filtered" : {
"filter" : {
"bool" : {
"must" : [
{ "term" : {"product_type" : "sometype"}}
]
}
}
}
},
"aggs" : {
"products" : {
"terms" : {
"field" : "store_id"
}
}
}
}'
Related
I've been trying to create some queries for my database but without success. This is the first time when dealing with queries in Firebase and find them a bit confusing.
I use a real-time database
My database looks like this :
-> users
->profile
->uid1
->email : "some#email.com"
->name : "some_name"
->favourite
->id1
->title : "some_title"
->date : "some_date"
->id : "id1"
->id2
->title : "some_title"
->date : "some_date"
->id : "id2"
->uid2
->email : "some#email.com"
->name : "some_name"
->favourite
->id1
->title : "some_title"
->date : "some_date"
->id : "id1"
->id2
->title : "some_title"
->date : "some_date"
->id : "id2"
The queries I've been trying to make:
Check whether a specific uid is already in the database.
Check whether a specific id from favourite is already in the database at a known uid.
Any ideas how to perform these queries?
Depends if you are using the real-time database or Firestore. But because you want to do queries I suggest to use Firestore and you could implement it this way:
// Create a path where you want the query to search
let storageReference = Firestore.firestore().collection("users/profile")
let query = storageReference.whereField("uid", isEqualTo: givenUID )
query.getDocuments { (snapshot, error) in
if let snapshot = snapshot {
for document in snapshot.documents {
let data = document.data()
}
}
}
In real-time database you can't use queries but you can implement it like this and see if the document is available:
let databaseRef = Database.database().reference(withPath: "users/profile/givenUID")
databaseRef.observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists() {
// UID is in the database
} else {
// UID not found
}
})
Then do the same with a reference for favorites!
I am new to Mongodb and I have to move my SQL Queries to mongodb now. I read the document and gained enough knowledge on writing mongodb QUeries but coming from MYSQL it will take time to get expertise on framing Mongo Queries.
I am trying to convert this query to Mongo for now using $Lookup
select * from orig_tbl emas
inner join cust-tbl_after_cleanup tmclient
on emas.state = tmclient.province
and emas.cons_city = tmclient.city
where
emas.state = 'VT' and
emas.can_match_address like concat('%',tmclient.street,'%')
and emas.can_cmp_name like concat('%',tmclient.name,'%')
and emas.can_match_address like concat('%',tmclient.house_num,'%')
and emas.can_match_address like concat('%',tmclient.postal_code,'%')
and emas.cons_city like concat('%',tmclient.city,'%')
and emas.State like concat('%',tmclient.province,'%')
group by tmclient.id,tmclient.name
As you can see I'm doing an inner join on multiple conditions and then doing a partial string match on number of cloumns. From the document I got to know how to do a multiple condition join but not sure how to do partial string match
Code so far:
aggregate(
[
{
'$match' : { 'name' : 'Walmart' }
},
{
'$lookup':
{
'from': 'entity_map_all_states',
'let': { 'order_city': "$city", 'order_qty': "$province" },
'pipeline': [
{ '$match':
{ '$expr':
{ '$and':
[
{ '$eq': [ "$cons_city", "$$order_city" ] },
{ '$eq': [ "$State", "$$order_qty" ] }
]
}
}
}
],
'as': "stockdata"
}
}
] )
I imported my MySQL database to MongoDB using MongoVUE.
First let me make an example of my tables:
Table0 = 1,500 entries
Table1 = 120,000 entries
Table2 = 18,000,000 entries
Table0 -> hasMany -> Table1 entries
Table1 -> hasMany -> Table2 entries
All tables have a _id key now but after the import both tables still have an id key from MySQL.
How do I updated table2's keys table1_id to match table1's _id key? Is it doable using a Mongo query or should I have to write a script for that? (The only language I know is PHP and Javascript/NodeJS)
Update 1
Using user #profesor79 answer I made this query where table1 = market_item_histories and table2 = market_items
db.market_item_histories.aggregate([
{
$lookup: {
from:"market_items",
localField: "market_item_id",
foreignField: "id",
as: "market_items_docs"
}
},
{
$unwind:"$market_items_docs"
},
{
$project: {
_id:1,
oldId:"$market_item_id",
market_item_id:"$market_items_docs._id",
date:1,
price:1,
amount:1,
created_at:1,
updated_at:1
}
},
{
$out:"marketItemHistories"
}
])
When running that code I get this Error:
assert: command failed: {
"errmsg" : "exception: Unrecognized pipeline stage name: '$lookup'",
"code" : 16436,
"ok" : 0
} : aggregate failed
Error: command failed: {
"errmsg" : "exception: Unrecognized pipeline stage name: '$lookup'",
"code" : 16436,
"ok" : 0
} : aggregate failed
at Error (<anonymous>)
at doassert (src/mongo/shell/assert.js:11:14)
at Function.assert.commandWorked (src/mongo/shell/assert.js:254:5)
at DBCollection.aggregate (src/mongo/shell/collection.js:1278:12)
at (shell):1:26
2016-04-29T14:13:48.223+0000 E QUERY Error: command failed: {
"errmsg" : "exception: Unrecognized pipeline stage name: '$lookup'",
"code" : 16436,
"ok" : 0
} : aggregate failed
at Error (<anonymous>)
at doassert (src/mongo/shell/assert.js:11:14)
at Function.assert.commandWorked (src/mongo/shell/assert.js:254:5)
at DBCollection.aggregate (src/mongo/shell/collection.js:1278:12)
at (shell):1:26 at src/mongo/shell/assert.js:13
this is a nice real life problem.
To get this done we can use aggregation framework and "join" tables, then write results in new collection.
After that the source can be renamed/deleted and our out can be renamed too.
This was done using mongo console.
Please find solution for joining table1 with table0, and use this to perform on others joins.
db.table1.aggregate([
{
$lookup:{
from:"table0",
localField: "table0_Id", // this is our join source
foreignField: "id", // this id field in table0 collection
as: "table0_docs"
}
},
{
$unwind:"$table0_docs"
},
{
$project:{
// very important list all fields here
_id:1,
data:1,
oldId:"$table0_Id",
referenceID:"$table0_docs._id",
}
},
{
$out:"newCollectionName"
}
])
AND OUTPUT DOCUMENT
{
"_id" : ObjectId("57234f5de63d33670e521892"),
"data" : "22",
"oldId" : 1,
"referenceID" : ObjectId("57234f33e63d33670e52188e")
}
Any comments welcome!
I have following mysql query in which I have done sum on two different fields called "count" and "population" and then divided sum(count)/sum(population) and then multiplied it with 100000 and finally grouping it by year.
Select year, cname, (sum(count)/sum(population))*100000 as total from cancer c where c.cname ="lung and bronchus" group by year;
I have written following query in mongodb but I am not sure how to project cname and year.
db.cancer_stats.aggregate([
{$match:{cname: "lung and bronchus"}},
{$group:{_id:"year"},
{total:{$multiply:[$divide:[$sum:"$count", $sum:"population"], 100000]}}
}])
can anyone guide me in solving this query?
I'm not sure what you mean by "solving the query", but that query is not valid in its current form. I think you want a pipeline like the following:
db.cancer_stats.aggregate([
{ "$match" : { "cname" : "lung and bronchus" } },
{ "$group" : { "_id" : "year", "t_count" : { "$sum" : "$count" }, "t_population" : { "$sum" : "$population" } } },
{ "$project" : { "result" : { "$multiply" : [100000, { "$divide" : ["$t_count", "$t_population"] } ] } } }
])
Does that answer your question?
I have a mongodb collection structured like this:
{ "client" : "CLIENTIDHERE", "amount" : 90, "invoice": "SOMEIDHERE", "date" : ISODate("2014-07-09T11:13:49.273Z") }
And need to select somehow all the payments made from a client.
In mysql I would do something like this, but with mongodb I have really no clue.
SELECT SUM(amount) payments,client FROM invoices GROUP BY client;
What I tried:
db.invoices.find({
$group: {
amount: {$sum: "$amount"}
}
}, {
$project:{
amount: "$amount",
client: "$client"
}
})
But it didn't work. What did I do wrong?
EDIT: I get the following error:
error: { "$err" : "Unsupported projection option: amount", "code" : 13097 }
Your $group step doesn't define what to GROUP BY. MongoDB's equivalent for the SQL GROUP BY is the _id field of the $group statement which is missing from your query. Also, when you want to use aggregation, you need to use .aggregate( instead of .find(.
db.invoices.aggregate({
$group: {
_id: "$client",
amount: { $sum: "$amount"}
}
});
This will write the client into the _id field. When you would rather want to have the field named client, you can fix that in the $project step, but otherwise the projection is not required in this case.