How do you do nested select in MongoDB analogous to
SELECT id FROM table1 WHERE id IN (SELECT id FROM table2)
MongoDB does not yet possess the ability to do subqueries which would allow this functionality.
I am sure it is something within the JIRA however, I could not immediately find it.
The only way currently is to actually pick the table, iterate the cursor pulling out the information and using that as part of a $in query as shown by #Bruno, like so:
ids=[];
for(i in db.c2.find({},{_id:1}){ // I have assumed id=_id
ids[ids.length]=i; // The default return of the index pos is actually _id
}
return db.c1.find({$in:ids});
As a mere example I wrote off of the top of my head.
This page contains comparator between SQL and MongoDB:
http://docs.mongodb.org/manual/reference/sql-comparison/
For example, you can to use a aggregation pipeline and where is the same as:
db.your_collection.aggregate({$match: {"id": {$in: ['id_0', 'id_1']} }})
A simple query as the same as:
db.your_collection.aggregate({field: "value"})
Mongodb official page has a lot of informations
Related
I would like help in executing a single query joining multiple tables (many-to-many), however I want to incorporate the Peewee PostgreSQL equivalent to Python's any() and all() operators.
Schema
Post: id, post_name
Tag: id, tag_name
Author: id, author_name
Post_Tags: post_id, tag_id
Post_Authors: post_id, author_id
Query
Given a list of multiple tag names and a list of multiple author names, I want all posts that have ANY tag that matches AND have ALL authors that matches:
Example
tag_list = [“Politics”, “Economy”]
author_list = [“Sarah”, “Alex”]
Query would return all posts that have at least one tag that is either “Politics” or “Economy” AND have as its authors “Sarah” and/or “Alex”. However if a post's authors are "Sarah" and "Christina", that post should NOT show up.
This is my current query but it does not satisfy all of my conditions:
query = Post
.select()
.join(PostTags)
.join(Tag)
.switch(Post)
.join(PostAuthors)
.join(Authors)
.where((Tag.name << tag_list) & (Author.name << author_list))
However I still need to iterate over my query to accomplish what I need:
filtered_posts = []
for post in query:
if all(author.name in author_list for author in post.authors):
filtered_posts.append(post)
Any tips on optimizing my query in Peewee? Thank you in advance!
You can use group-by/having to ensure the count of matched authors is equal to the count you are inputting and the count of tags is greater-than or equal to 1. You can also separate the queries and do a UNION or INTERSECT.
The SQL "EXISTS" helper can be useful for the tags portion of your query if you want to use a subquery rather than a JOIN.
I have a simple json:
{
"id": 1,
"name": "John",
"login": "2019-02-13"
}
This kind of documents are stored in Couchbase, but for now I would like to create index (or list in some other, well time way) which should filter all documents where login is older then 30 days. How should I create it in Couchbase and get this in Scala?
For now I get all documents from database and filter them in API, but I think it is not very good way. I would like to filter it on database side and retrieve only documents which have login older then 30 days.
Now, in Scala I have only the method only to get docs by id:
bucket.get(id, classOf[RawJsonDocument])
I would recommend taking a look at N1QL (which is just SQL for JSON). Here's an example:
SELECT u.*
FROM mybucket u
WHERE DATE_DIFF_STR(NOW_STR(), login, 'day') > 30;
You'll also need an index, something like:
CREATE INDEX ix_login_date ON mybucket (login);
Though I can't promise that's the best index, it will at least get you started.
I used DATE_DIFF_STR and NOW_STR, but there are other ways to manipulate dates. Check out Date Functions in the documentation. And since you are new to N1QL, I'd recommend checking out the interactive N1QL tutorial.
The following query is more efficient because it can push the predicate to IndexScan when index key matched with one side of predicate relation operator. If you have expression that derives from index key, it gets all the values and filter in the query engine.
CREATE INDEX ix_login_date ON mybucket (login);
SELECT u.*
FROM mybucket AS u
WHERE u.login < DATE_ADD_STR(NOW_STR(), 'day', -30) ;
I am trying to search based on multiple conditions which works but the problem is that does not behave like this.
Assuming i have a search query like
Orders.find({$or: {"status":{"$in":["open", "closed"]},"paymentStatus":{"$in":["unpaid"]}}}
)
and i add another filter parameter like approvalStatus it does not leave the previously found items but rather it treats the query like an AND that will return an empty collection of items if one of the queries does not match.
How can i write a query that regardless of what is passed into it, it will retain previously found items even if there is no record in one of the conditions.
like a simple OR query in sql
I hope i explained this well enough
Using $or here is the right approach, but its value needs to be an array of query expressions, not an object.
So your query should look something like this instead:
Orders.find({$or: [
{"status": {"$in": ["open", "closed"]}},
{"paymentStatus": {"$in": ["unpaid"]}},
{"approvalStatus": {"$in": ["approved"]}}
]})
I want to know what is the need of first curly brace {} after find here in this query.
db.mycol.find({},{"title":1,_id:0})
It is an empty query, in the sense of a limiting boundary. So
db.mycol.find({},{"title":1,_id:0})
would basically translate to
Show me the title, but not the _id (as you would do by default) for all documents of the mycol collection in the current database.
Let's say you want all the titles written by Alan Turing. So you could modify the query part like this:
db.mycol.find({"author":"Alan Turing"},{"title":1,_id:0})
In general, MongoDB's find operation can be described like this
db.collection.find(query,projection)
For more detailed information, you might want to read find's documentation.
The first Curly braces is used as a where condition in MySql
Check out this Link - SQL to MongoDB Mapping Chart
MySQL
SELECT user_id, status FROM users WHERE status = "A"
MongoDB
db.users.find(
{ status: "A" },
{ user_id: 1, status: 1, _id: 0 }
)
This is called projection and tells which fields to show. For example here you show only title. It is something like Select title from mycol; If you will not specify projection it will return everything, which is close to select * from mycol;
_id is always shown, unless you hide it explicitly with _id: 0. Another thing is that you can not mix 0 and 1 (except for _id). But one more time - read FAQ.
You should refer this link for better explanation
http://docs.mongodb.org/manual/reference/operator/projection/positional/
first of all, projection does not return the first result it finds it tells mongo what to return.
.findOne(query) will LIMIT result to one or find(query).limit(1) will also do the same.
You say you are trying to "get all" your data.
a standard find type query will get your started...
find({mongo:query},{mongo:projection})
but limits results to a cursor from the mongo shell*
How do I use wild character in MongoDB while use Update
I want to do like below in mongo db is it possible to write it.
update emp set sal=sal*2 where ename like '%Pr%';
emp is the collection name
columns: ename, eno, sal
You can use a regexp for your wildcard search, but you have to do the update client-side, because mongoDB is not able to access the content of another field (or the field's content itself) while updating:
db.emp.find( { ename: /Pr/ } ).forEach( function (x) {
x.sal = x.sal * 2;
db.emp.save( x );
});
In MongoDB 2.6 you will be able to do that update enirely server-side using the new $mul operator. As of the time of this posting 2.6 is still in pre-relase; you can check the MongoDB download page for availability. Check the release notes for a complete list of changes and new features.
Also note that you should use an anchored regexp query, that is one that begins with ^, if you know that the string you are searching for is at the beginning of the field. Anchored regexp queries are more efficient because they can use an index and avoid a table scan.
Here is the query with these two changes:
db.emp.update({ename: /^Pr/}, {$mul: {sal: 2}}, {multi: true})