If I have a collection that contains collection names in it, is there a syntax in AQL that allows you to use dynamic collection names?
Here is an example of what I'm looking for. A collection called master has many documents, with a .state of Active or Disabled. The collection has a key called collection_name which is the name of another collection in this database.
FOR doc IN master
FILTER doc.state == 'Active'
FOR c IN COLLECTION(doc.collection_name) <--- invented command called COLLECTION
RETURN {
'collection_name': doc.collection_name,
'contents': c
}
I'm trying to retrieve all documents from all collections marked as Active in the master collection.
Is there a way to do this in one AQL query without having to break it up into an initial query on master followed by n queries for each of the collections returned?
As I've concluded from this ArangoDB issue there is no way to truly use dynamic collection names.
However you could use any AQL function as workaround. See the last comment on the issue for a full explanation.
Related
I am making an Admin dashboard. I want to show all user's details and their orders. When I want to fetch all documents inside the user collection its returning empty. For more In user collection, each document has some sub-collection. In the account sub-collection, there is a document exists with name details where user account details are available as shown in snapshots.
My code is
export function getUsers() {
return firebase.firestore().collection("users").get();
}
If you store user's details directly in the document instead of 'account' sub-collection then fetching "users" collection will return all users' documents with their data. If you say there's no reason then I'd recommend doing this.
Other option would be to use collectionGroup query on "account" which will fetch all the documents from sub-collections named as "account" i.e. giving you every user's account details.
const snap = await db.collectionGroup('account').get()
const users = snap.docs.map(d => ({id: doc.ref.parent.parent.id, data: d.data()))
Here, id is user's document ID.
Firestore queries only access a single collection, or all collections with a specific name. There is no way to query a collection based on values in another collection.
The most common options are:
Query the parent collection first, then check the subcollection for each document. This approach works best if you have relatively few false positives in the parent collection.
Query all child collections with a collection group query, then check the parent document for each result. This approach works best if you have relatively few false positive in your child collection query.
Replicate the relevant information from the child documents into the parent document, and then query the parent collection based on that. For example, you could add a hasOrders field or an orderCount in the user document. This approach always gives optimal results while querying, but requires that you modify the code that writes the data to accommodate.
The third approach is typically the best for a scalable solution. If you come from a background in relation databases, this sort of data duplication may seen unnatural, but it is actually very common in NoSQL databases where you often have to change your data model to allow the queries your app needs.
To learn more about this, I recommend reading NoSQL data modeling and watching Getting to know Cloud Firestore.
I would like to delete all documents in all MongoDB collections. Is there a way to delete all documents in all collections.
I was using db.collection.remove({}) but it only removes all documents in one collection. Is there any command to do? I'm using NodeJS mostly, maybe there is a chance to use NodeJS to delete all documents in all collections?
Sorry if the question is dumb, just started working in MongoDB.
As already suggested - You can either use .dropDatabase() to drop entire database or .collection.drop() to drop a collection or if it's just to delete all documents in all collections then you need to iterate on list of collections and implement either .collection.remove() or .collection.deleteMany() or .findAndModify() without any filter in query condition.
To delete documents in each collection individually :
first list all collection names using .getCollectionNames() and then remove documents.
let colls = db.getCollectionNames() // Mongo shell can accept .Js Func's, if you've more collections you can use parallel as well
colls.forEach(eachColl => db[eachColl].remove({})) // or .deleteMany() or . findAndModify()
Doing this way, you'll still have the database and empty collections existing on MongoDB server. Maybe you can comeback after sometime check list of collections available or maybe rename few etc.
But if you just simply don't want to look at collection names that use to exist in any near future, go ahead with drop commands preferable drop database as you wanted to delete all docs from all collections - why it's preferred ? is because unlike SQL databases MongoDB automatically creates a database and a collection if you write a document for the first time to a collection in a DB. So in MongoDB you might not need to maintain databases with empty collections.
Assume you're querying on collection named girlfriend which is in mylife database - Let's say it's already deleted/missing/never existed then .find() would return [] empty array same like querying on empty collection on a DB - this is the advantage with MongoDB as it doesn't throw an error on mismatched names.
I read that mongodb has TTL (Time to live) indexes that can be activated for document.
But does it work if document structure is as follows?
username: 'user x',
activity: [
{type:a, desc:1, timestamp:timestamp},
{type:b, desc:2, timestamp:timestamp},
{type:b, desc:3, timestamp:timestamp},
etc.
]
Is there possibility to set TTL based on timestamp+7days of each array item so that only those expires but recent ones are kept?
Read the documentation carefully, The TTL index can be applied to an array but it will delete the whole document when expired not just the element inside the array.
However, you could split the array out into many documents?
There's currently no way to delete specific elements from an array using a TTL index. There's a feature request for this, but it seems like at the moment the best way to do this is to create a separate collection that links to the _id of your documents.
So in your case, instead of adding an activity array to all your users, you create an extra activities collections which contains documents like this:
{type:a, desc:1, timestamp:timestamp, userId:ObjectId("611636e533f29e4bd6683b05")}
{type:b, desc:2, timestamp:timestamp, userId:ObjectId("611636e533f29e4bd6683b05")}
{type:b, desc:3, timestamp:timestamp, userId:ObjectId("611636e533f29e4bd6683b05")}
I am using Azure DocumentDB. I only have one collection with heterogenous document types. I am using a type parameter to distinguish between different document types. I am making use of their SQL-like query language to get documents as follows:
SELECT * FROM Collection c WHERE c.ID = 123
I am getting my connection information, including the Endpoint URI, AuthKey, Database name and Collection name, from a configuration file. It seems like I can use any value for "Collection c" and it essentially just becomes an alias for the whole collection. So what is the point of the FROM section of my query?
I think you already got it :)
FROM allows you to set an alias to refer to the collection in other clauses. This may make more sense to you when you include multiple references (e.g. using a JOIN to form a cross-product with nested array elements).
For example:
SELECT food.description, tag.name
FROM food
JOIN tag IN food.tags
WHERE food.id = "09052"
In the query above, we are using referencing both the collection as well as nested array elements within a projection.
You can try this query out on the query demo website.
I have a Tags collection which contains documents of the following structure:
{
word:"movie", //tag word
count:1 //count of times tag word has been used
}
I am given an array of new tags that need to be added/updated in the Tags collection:
["music","movie","book"]
I can update the counts all Tags currently existing in the tags collection by using the following query:
db.Tags.update({word:{$in:["music","movies","books"]}}, {$inc:{count:1}}), true, true);
While this is an effective strategy to update, I am unable to see which tag values were not found in the collection, and setting the upsert flag to true did not create new documents for the unfound tags.
This is where I am stuck, how should I handle the bulk insert of "new" values into the Tags collection?
Is there any other way I could better utilize the update so that it does upsert the new tag values?
(Note: I am using Node.js with mongoose, solutions using mongoose/node-mongo-native would be nice but not necessary)
Thanks ahead
The concept of using upsert and the $in operator simultaneously is incongruous. This simply will not work as there is no way to different between upsert if *any* in and upsert if *none* in.
In this case, MongoDB is doing the version you don't want it to do. But you can't make it change behaviour.
I would suggest simply issuing three consecutive writes by looping through the array of tags. I know that's it's annoying and it has a bad code smell, but that's just how MongoDB works.