pymongo: bulk write operations
https://pymongo.readthedocs.io/en/stable/examples/bulk.html#ordered-bulk-write-operations
{
"mappings": {
"dynamic": true,
"fields": {
"plot_embedding_hf": {
"dimensions": 384,
"similarity": "dotProduct",
"type": "knnVector"
}
}
}
}
# main.py
@app.on_event("startup")
def startup_event():
connect(host=DATABASE_URL, alias=settings.MONGO_ENGINE_ALIAS)
@app.on_event("shutdown")
def shutdown_event():
disconnect(alias=settings.MONGO_ENGINE_ALIAS)
https://pymongo.readthedocs.io/en/stable/api/bson/index.html
Python Type |
BSON Type |
Supported Direction |
---|---|---|
None |
null |
both |
bool |
boolean |
both |
int 1 |
int32 / int64 |
py -> bson |
bson.int64.Int64 |
int64 |
both |
float |
number (real) |
both |
str |
string |
both |
list |
array |
both |
dict / SON |
object |
both |
date |
both |
|
bson.regex.Regex |
regex |
both |
compiled re 4 |
regex |
py -> bson |
bson.binary.Binary |
binary |
both |
bson.objectid.ObjectId |
oid |
both |
bson.dbref.DBRef |
dbref |
both |
None |
undefined |
bson -> py |
bson.code.Code |
code |
both |
str |
symbol |
bson -> py |
bytes 5 |
binary |
both |
NOTES:
Optional. When true,
replaceOne()
either:
- Inserts the document from the replacement parameter if no document matches the filter.
- Replaces the document that matches the filter with the replacement document.
- MongoDB will add the _id field to the replacement document if it is not specified in either the filter or replacement documents. If _id is present in both, the values must be equal.
- To avoid multiple upserts, ensure that the query fields are uniquely indexed.
- Defaults to false.
class Example:
async def insert_or_update_many(
self,
db_from: AsyncIOMotorDatabase,
db_to: AsyncIOMotorDatabase,
model: BaseModel,
_filter: dict = {}
) -> Any:
assert issubclass(model, BaseModel)
try:
query = db_from.find(filter=_filter)
requests = [
ReplaceOne(
{'_id': raw['_id']},
model(**raw).dict(),
upsert=True
) async for raw in query
]
result = await db_to.bulk_write(requests)
res_str = f'''New:\n-{result.upserted_ids}\nModified:\n-{result.modified_count}'''
logger.info(res_str)
return res_str
except Exception as err:
logger.warn(f'{err}')
raise Exception(err)
https://motor.readthedocs.io/en/stable/tutorial-asyncio.html#updating-documents
Provides same functionality as update_one but updates all documents that match filter.
await coll.update_many(
{'i': {'$gt': 100}},
{'$set': {'key': 'value'}}
)
@pytest.fixture(scope='session')
async def get_random_db_list():
count = await db[collection].estimated_document_count()
if count < 5:
skip = 0
else:
count = count - 1
skip = random.randint(1, count)
query = db[collection].find(
{},
{
'c_id': 1,
'u_id': 1
},
skip=skip,
limit=3
)
result = [i async for i in query]
yield result
query = await db['collection_name'].find().distinct(['field_id'])
print(query)
from bson import SON
query = await db.command(
SON(
[
("distinct", 'collection_name'),
("key", "_id")
]
)
)
return query['values']
async def get_distinct_value_with_query(
some_id: str,
collection: str,
db: AsyncIOMotorDatabase
) -> list:
query = await db[collection].distinct(
'distinct_val',
{'some_id': some_id})
pprint(query)
return query
from pymongo import MongoClient
collection = MongoClient()['mydatabase']['mycollection']
for testy in collection.find().distinct('stores'):
print(testy)
# or
for testy in collection.distinct('stores', {'dept': 'A'}):
print(testy)
# or
query = db[collection].find(
{'some_id': some_id},
{'project_field': 1}
)
return set([ModelSchema(**raw).dict() async for raw in query])
# or
collection.insert_many([{'name': "a", 'age': 23},
{'name': "a", 'age': 23},
{'name': "a", 'age': 24},
{'name': "b", 'age': 23},
{'name': "b", 'age': 23},
{'name': "b", 'age': 23}])
for record in collection.aggregate([{'$group': {'_id': {'name': '$name', 'age': '$age'}}}]:
print(record)
dic = {
'shipto_ref': [DBRef('collection_name', ObjectId(obj_id))]
}
MongoDB offers two kinds of indexes out-of-the-box:
- Btree indexes
- geospatial indexes.
NOTES:
- Index creation locks the database by default.
- For large collections index creation can be time consuming.
- Indexc creation can be done in the background for production databases without blocking.
The btree indexes in MongoDB are much the same as the equivalents in MySQL or PostgreSQL.
When in a relational system you would put an index on a column to get fast lookups on that field, you do an analogous thing in MongoDB by placing an index on a particular property in a collection.
With an RDBMS, `MongoDB indexes can span multiple fields (a.k.a. compound indexes)` useful if you know in advance that you will be querying based on the value of more than a single property.
A compound index would be useful for example if you were querying documents by first name and last name.
In MongoDB, btree indexes can have a “direction”.
This direction is only useful in the case of compound indexes, where the
index direction should match the sort direction or range query direction for optimal
performance.
For example, if you are querying a range (say, A through C) on first name and last name and then sorting in ascending order on last name, your compound index direction should also be ascending.
Using a btree index will incur a performance hit on writes, as the database must now update the index in addition to the data.
For this reason, it is wise to choose your indexes carefully.
Avoid superfluous indexes if at all possible.
Indexes also take up valuable storage—not so much of an issue with on-disk space today given the low price-per-terrabyte—but in memory, too.
Your database will run fastest when it resides entirely in memory, and indexes can considerably add to its size.
It is a classic Computer Science time vs. space tradeoff scenario.
MongoDB btree indexes can also be used to enforce a unique constraint on a particular property in a collection.
By default, the _id primary key property has a unique index created in MongoDB.
The unique constraint will prevent the protected property from ever having a duplicate value within the collection.
This can be useful for values which are expected to be globally unique in the collection—a common example being user-names.
Beware of over-reliance on this feature, however, as in the current implemen-tation of sharding, unique indexes are supported only on the _id property—otherwise
Btree indexes also transparently support indexing multi-value properties, that is, properties where the value is an array.
Each item in the array will be properly stored in the index to enable fast retrieval of the parent document.
This can be useful for performant implementations of tagging, where each tag is stored as a string inside a “tags” list property on the document.
Lookups for documents matching one or more of those tags (potentially using the $in query operator) will then be looked up in the “tags” index.
Furthermore, btree indexes are equally well supported when placed on embedded sub-documents.
If, for example, you store email addresses as embedded sub-documents, and you wish to be able to look up by the value of the email address using an index, MongoDB allows this.
Hence the following document and query could take advantage
user_doc = {
"username":"foouser",
"emails":[
{
"email":"foouser1@example.com",
"primary":True
},
{
"email":"foouser2@example2.com",
"primary":False
},
{
"email":"foouser3@example3.com",
"primary":False
}
]
}
dbh.users.insert(user_doc)
dbh.users.insert(user_doc)
# If we place an index on property "emails.email",
# e.g. dbh.users.create_index("emails.email")
# this find_one query can use a btree index
user = dbh.users.find_one(
{"emails.email": "foouser2@example2.com"}
)
For example to create an index on the username property of a collection called users, you could write the following:
# Create index on username property
dbh.users.create_index("username")
To create a compound index, for example on the first_name
and last_name
, with an acending direction
, you could specify:
# Create a compound index on first_name and last_name properties
# with ascending index direction
dbh.users.create_index([("first_name", pymongo.ASCENDING), ("last_name", pymongo.ASCENDING)])
Indexes in MongoDB each have names.
By default, MongoDB will generate a name, but you may wish to give a custom name—particularly for compound indexes where the generated names are not especially readable by humans.
To give a custom name during creation, supply the name=<str>
parameter to the create_index()
method:
# Create a compound index called "name_idx" on first_name and last_name properties with ascending index direction
dbh.users.create_index(
[
("first_name", pymongo.ASCENDING),
("last_name", pymongo.ASCENDING)
],
name="name_idx")
To specify that an index should be built in the background, pass the background=True
parameter to the create_index()
method:
# Create index in the background
# Database remains usable
dbh.users.create_index("username", background=True)
As mentioned earlier in this section, MongoDB btree indexes can be used to enforce a uniqueness constraint on a particular property.
Unique constraints can be applied to both single-key indexes and compound indexes.
To create an index with a unique constraint, pass the unique=True parameter
to the create_index()
method:
# Create index with unique constraint on username property
dbh.users.create_index("username", unique=True)
Be aware that unique indexes in MongoDB do not function exactly the same as indexes in RDBMS systems.
In particular, a document with a missing property will be added to the index as if it the value of that property were null.
This means that when a unique constraint is added to a btree index in MongoDB, the database will prevent you from having multiple documents in the collection which are missing the indexed property.
For example, if you have created a unique index for the username property in a users collection, only one document in that collection may be permitted to lack a username property.
Writes of additional documents without a username property will raise an exception.
If you try to add a unique index to a collection which already contains duplicates on the specified property, MongoDB will (unsurprisingly) raise an exception.
However, if you don’t mind throwing away duplicate data, you can instruct MongoDB to drop all but the first document it finds using the dropDups
or drop_dups
parameter:
# Create index with unique constraint on username property
# instructing MongoDB to drop all duplicates after the first document it finds.
dbh.users.create_index("username", unique=True, drop_dups=True)
# Could equally be written:
dbh.users.create_index("username", unique=True, dropDups=True)
Over time, your schema may evolve and you may find that a particular index is no longer needed.
Fortunately, indexes are easy to remove in MongoDB.
The Collection.drop_index()
method deletes one index at a time.
If you created your index with a custom name (as described above), you must supply this same name to the drop_index()
method in order to delete it.
For example:
# Create index on username property called "username_idx"
dbh.users.create_index("username", name="username_idx")
# Delete index called "username_idx"
dbh.users.drop_index("username_idx")
If, on the other hand, you did not give your index a custom name, you can delete by passing the original index specifier.
For example:
# Create a compound index on first_name and last_name properties
# with ascending index direction
dbh.users.create_index([("first_name", pymongo.ASCENDING), ("last_name",
pymongo.ASCENDING)])
# Delete this index
dbh.users.drop_index([("first_name", pymongo.ASCENDING), ("last_name",
pymongo.ASCENDING)])
All indexes in a collection can be dropped in a single statement using the Collection.drop_indexes()
method.
Updating or changing the schema of a production database.
When developing a database-driven application, one concern that programmers must take into account is schema evolution.
Typically, this is taken care of using a set of migration scripts that upgrade the database from one version of a schema to another.
Before an application is actually deployed with “live” data, the “migrations” may consist of dropping the database and re-creating it with a new schema.
Once your application is live and populated with customer data, however, schema changes require complex migration scripts to change the format of data while preserving its content.
Relational databases typically support migrations via the ALTER TABLE statement, which allows the developer to add or remove columns from a table.
For instance, suppose we wanted to add a short description field to our nodes table from Table 2-1.
The SQL for this operation would be similar to the following:
ALTER TABLE nodes
ADD COLUMN short_description varchar(255);
The main drawbacks to the ALTER TABLE
statement is that it can be time consuming to run on a table with a large number of rows, and may require that your application experience some downtime while the migration executes, since the ALTER TABLE
statement needs to hold a lock that your application requires to execute.
In MongoDB, we have the option of doing something similar by updating all documents
in a collection to reflect a new field:
db.nodes.update(
{},
{$set: { short_description: '' } },
false, // upsert
true // multi
);
This approach, however, has the same drawbacks as an ALTER TABLE
statement: it can be slow, and it can impact the performance of your application negatively.
Another option for MongoDB users is to update your application to account for the absence of the new field.
In Python, we might write the following code to handle re‐trieving both “old style” documents (without a short_description field) as well as “new
style” documents (with a short_description field):
def get_node_by_url(url):
node = db.nodes.find_one({'url': url})
node.setdefault('short_description', '')
return node
Once we have the code in place to handle documents with or without the short_description
field, we might choose to gradually migrate the collection in the background, while our application is running.
For instance, we might migrate 100 documents at a time:
def add_short_descriptions():
node_ids_to_migrate = db.nodes.find(
{'short_description': {'$exists':False}}).limit(100)
db.nodes.update(
{ '_id': {'$in': node_ids_to_migrate } },
{ '$set': { 'short_description': '' } },
multi=True)
Once the entire collection is migrated, we can replace our application code to load the
node by URL to omit the default:
def get_node_by_url(url):
node = db.nodes.find_one({'url': url})
return node
Use up‐sert and increment operations to calculate statistics, allowing simple range-based queries
Individual documents growing significantly after they are created:
- Document growth forces MongoDB to move the document on disk, slowing things down.
Collection scans:
- The more documents that MongoDB has to examine to fulfill a query, the less efficient that query will be.
Documents with a large number (hundreds) of keys:
- Due to the way MongoDB’s internal document storage BSON stores documents, this can create wide variability in access time to particular values.
$where
in $match
queries as part of the aggregation pipeline.$near
or $nearSphere
in $match queries as part of the aggregation pipeline. As an alternative, you can either:$geoNear
stage instead of the $match stage.$geoWithin
query operator with $center
or match` stage.$text
in the $match
stage, the $match
stage has to be the first stage of the pipeline.{
"$match": {
"orderdate": {
"$gte": ISODate("2020-01-01T00:00:00Z"),
"$lt": ISODate("2021-01-01T00:00:00Z"),
},
}
}
{
"$lookup":
{
"from": "other_collection",
"let": {
"current_collection_field": "$current_labels.label"
},
"as": "updated",
"pipeline": [
{
"$match": {
"$expr": {"$nin": ["$LabelDetection.Text", "$$labels"]}
},
},
{
"$match": {
"$expr": {
"$not": [
{ "$in": ["$LabelDetection.Text", "$$current_collection_field"] }
]
},
},
}
]
}
}
$set
is alias for this.Preserving Non-Existence. The field further_info.reported is an optional field in this scenario.
The field may not always appear in a document, as illustrated by one of the three documents in the example.
If a field is not present in a document, this potentially significant fact should never be lost.
The pipeline includes additional logic for the further_info.reported field to preserve this information.
The pipeline ensures the field is not included in the output document if it didn't exist in the source document.
A $ifNull conditional operator is used, which returns the $$REMOVE marker flag if the field is missing, instructing the aggregation engine to omit it
{
"$set": {
"order_date": {"$toDate": "$order_date"},
"value": {"$toDecimal": "$value"},
"further_info.item_qty": {"$toInt": "$further_info.item_qty"},
"further_info.reported": {"$switch": {
"branches": [
{"case": {"$eq": [{"$toLower": "$further_info.reported"}, "true"]}, "then": true},
{"case": {"$eq": [{"$toLower": "$further_info.reported"}, "false"]}, "then": false},
],
"default": {"$ifNull": ["$further_info.reported", "$$REMOVE"]},
}},
}
}
Best
{
"$set": {
"name": {
"$cond": {
"if": {
"$regexMatch": {
"input": "$name",
"regex": /^The /
}
},
"then": {
"$replaceOne": {
"input": "$name",
"find": "The ",
"replacement": ""
}
},
"else": "$name"
}
}
}
}
Better
{
"$set": {
"name": {
"$replaceOne": {
"input": "$name",
"find": "The ",
"replacement": ""
}
}
}
}
Good
$set: {
name: { $ltrim("$name","The ") }
}
{
"$addFields": {
"shipto_id": {
"$arrayElemAt": ["$shipto_ref", 0]
}
}
}
Can promote an embedded document to the top-level
.You can also specify a new document as the replacement.
// Group by customer
{
"$group": {
"_id": "$customer_id",
"first_purchase_date": {"$first": "$orderdate"},
"total_value": {"$sum": "$value"},
"total_orders": {"$sum": 1},
"orders": {"$push": {"orderdate": "$orderdate", "value": "$value"} },
}
}
https://www.mongodb.com/docs/manual/reference/operator/aggregation/switch/
Evaluates a series of case expressions.
When it finds an expression which evaluates to true,
$switch
executes a specified expression and breaks out of the control flow.The following conditions cause failure with an error:
field is missing
or is not an array
with at least one entry
.
// insert_many data
{ "_id" : 1, "name" : "Susan Wilkes", "scores" : [ 87, 86, 78 ] }
{ "_id" : 2, "name" : "Bob Hanna", "scores" : [ 71, 64, 81 ] }
{ "_id" : 3, "name" : "James Torrelio", "scores" : [ 91, 84, 97 ] }
db.grades.aggregate( [
{
$project:
{
"name" : 1,
"summary" :
{
$switch:
{
branches: [
{
case: { $gte : [ { $avg : "$scores" }, 90 ] },
then: "Doing great!"
},
{
case: { $and : [ { $gte : [ { $avg : "$scores" }, 80 ] },
{ $lt : [ { $avg : "$scores" }, 90 ] } ] },
then: "Doing pretty well."
},
{
case: { $lt : [ { $avg : "$scores" }, 80 ] },
then: "Needs improvement."
}
],
default: "No scores found."
}
}
}
}
] )
{ "_id" : 1, "name" : "Susan Wilkes", "summary" : "Doing pretty well." }
{ "_id" : 2, "name" : "Bob Hanna", "summary" : "Needs improvement." }
{ "_id" : 3, "name" : "James Torrelio", "summary" : "Doing great!" }
"label_value_2": {
"$switch": {
"branches": [
{
case: { "$eq": [ { "$type": "$label_value.value"}, "string" ] }, then: "string",
case: { "$ne": [ { "$type": "$label_value.value"}, "string" ] }, then: "not string"
}
],
default: "$label_value.value"
}
}
{
"$set": {
"label_value": {
"$cond": {
"if": {"$eq": [ { "$type": "$label_value.value" }, "string" ] },
"then": { "$replaceAll": {"input": "$label_value.value", "find": "U+0024", "replacement": "" }
},
"else": {"label": "$label_value.label", "value": "$label_value.value"}
}
}
}
},// Or
{
"$set": {
"label_value_2": {
"$cond": [
{
"$or": [
{"$eq": [ { "$type": "$label_value.value"}, "string" ] }
]
},
"$$REMOVE"
]
}
}
}
// {"$replaceOne": { "input": "$label_value.value", "find": "\\$", "replacement": "" },
// { $project: { item: 1, description: { $trim: { input: "$description" } } } }
// { $project: { item: 1, description: { $trim: { input: "$description" } } } }
//
A ternary operator that evaluates one expression, and depending on the result, returns the value of one of the other two expressions.
Accepts either three expressions in an ordered list or three named parameters.
_id
field not present, will create it automatically.into
argument does not exist.
if output collection doesn't exist
, on must be _id
field.{
"$merge": {
"into": "stage_two",
"on": "_id",//this must be an index
"whenMatched": "replace",
"whenNotMatched": "insert"
}
}
Creates a new document and insert it into a collection.
def new_document_as_dict(
self,
doc_id: str,
into: str,
on: str
) -> list[dict[str, dict]]:
AGG = [
{
"$match": {
"doc_id": doc_id,
'mapping_key': { '$ne': None }
}
},
{
"$group": {
"_id": "$doc_id",
"doc_id": { "$first": "$doc_id" },
"doc_url": { "$first": "$doc_url" },
"label_value": { "$addToSet": { "label": "$mapping_key", "value": "$Value.Text" }
}
}
},
{
"$set": {
"label_value": {
"$sortArray": {
"input": "$label_value",
"sortBy": { "label": 1 }
}
}
}
},
{
"$merge": {
"into": into,
"on": on,
"whenMatched": "replace",
"whenNotMatched": "insert"
}
}
]
return AGG
Used on MongoDB version 6.0
Purpose of this query is to clean semi-structured data.
This aggregation query does the following:
string
and starts with a $
$
from string by replacing with empty string.class CleanData:
def clean_semi_structured_data(
self,
_id: str,
field2: dict,
same_collection: str,
on: str = '_id'
) -> list:
AGG = [
{
"$match": {
"_id": _id,
}
},
{
"$set": {
"ValueDetection.Text": {
"$cond": {
"if": {
"$and": [
# ensure value is bson type string
{ "$eq": [{ "$type": "$ValueDetection.Text" }, "string"] },
{ "$regexMatch": { "input": "$ValueDetection.Text", "regex": "^\\$", "options": "im" } }
]
},
"then": { "$replaceOne": { "input": "$ValueDetection.Text", "find": { "$literal": "$" }, "replacement": "" } },
"else": "$ValueDetection.Text"
}
}
}
},
{
"$group": {
"_id": "$_id",
}
},
{
"$addFields":{
"field1": [],
"field2": [field2]
}
},
{
"$merge": {
"into": same_collection,
"on": on,
"whenMatched": "replace",
"whenNotMatched": "insert"
}
}
]
return AGG
{
_id: '$Type.Text',
'count': {'$sum': 1}
}
COUNT_BY_VALUE_TYPE = [
{
"$project": {
"ValueDetection.Text": {
"$type": "$ValueDetection.Text"
}
}
},
{
"$group": {
"_id": "$ValueDetection.Text",
"count": {
"$sum": 1.0
}
}
}
]
client = MongoClient('mongodb+srv://...')
result = client['test']['comments'].aggregate([
{
'$group': {
'_id': '$resto',
'comments': {
'$push': '$com'
}
}
}
])
result = client['test']['comments'].aggregate([
{
'$group': {
'_id': '$thread_ref',
'comments': {
'$push': '$com'
}
}
}, {}
])
result = client['test']['comments'].aggregate([
{
'$sort': {
'thread_ref': 1
}
}, {
'$group': {
'_id': '$resto',
'comments': {
'$push': '$$ROOT'
}
}
}, {
'$project': {
'comments.no': 1,
'comments.com': 1,
'comments.my_time': 1,
'comments.ids': 1
}
}
])
var pipeline = [
// Change field from a string to a date, filling in the gaps
{"$set": {
"paymentDate": {
"$let": {
"vars": {
"txt": "$paymentDate", // Assign "paymentDate" field to variable "txt",
"month": {"$substrCP": ["$paymentDate", 3, 3]}, // Extract month text
},
"in": {
"$dateFromString": {"format": "%d-%m-%Y %H.%M.%S.%L", "dateString":
{"$concat": [
{"$substrCP": ["$$txt", 0, 3]}, // Use 1st 3 chars in string
{"$switch": {"branches": [ // Replace month 3 chars with month number
{"case": {"$eq": ["$$month", "JAN"]}, "then": "01"},
{"case": {"$eq": ["$$month", "FEB"]}, "then": "02"},
{"case": {"$eq": ["$$month", "MAR"]}, "then": "03"},
{"case": {"$eq": ["$$month", "APR"]}, "then": "04"},
{"case": {"$eq": ["$$month", "MAY"]}, "then": "05"},
{"case": {"$eq": ["$$month", "JUN"]}, "then": "06"},
{"case": {"$eq": ["$$month", "JUL"]}, "then": "07"},
{"case": {"$eq": ["$$month", "AUG"]}, "then": "08"},
{"case": {"$eq": ["$$month", "SEP"]}, "then": "09"},
{"case": {"$eq": ["$$month", "OCT"]}, "then": "10"},
{"case": {"$eq": ["$$month", "NOV"]}, "then": "11"},
{"case": {"$eq": ["$$month", "DEC"]}, "then": "12"},
], "default": "ERROR"}},
"-20", // Add hyphen + hardcoded century 2 digits
{"$substrCP": ["$$txt", 7, 15]} // Use time up to 3 millis (ignore last 6 nanosecs)
]
}}
}
}
},
}},
// Omit unwanted fields
{
"$unset": [
"_id"
]
}
];
db.feedback.aggregate( [
{
$addFields: {
"email": { $regexFindAll: { input: "$comment", regex: /[a-z0-9_.+-]+@[a-z0-9_.+-]+\.[a-z0-9_.+-]+/i } }
}
},
{
$set: {
email: "$email.match"
}
}
])
db.review.aggregate([
{
“$addFields”: {
“sentiment”: {
“$cond”: {
“if”:{“$gt”:["$stars", 3]}, “then”: 1, “else”: 0
}
}
}
},
{"$out":"review_train"}
]);
class Pipelines(QuerySet):
def metric_one(self):
indeed_value_counts = [
{'$match': {'job_title': {'$not': {'$size': 0}},
'company': {'$not': {'$size': 0}}}
},
{'$group': {'_id': {'title': {'$toLower': '$job_title'},
'comp': {'$toLower': '$company'}},
'count': {'$sum': 1}}
},
{'$match': {'count': {'$gte': 2}}
},
{'$sort': {'count': -1}
},
{'$out': 'comp_job_vals'}]
return self.aggregate(indeed_value_counts)
def indeed_single_count_aggregation(self, field):
'''group with toLower?'''
indeed_counts = [
{'$match': {f'{field}': {'$not': {'$eq': ""}}}
},
{'$group': {'_id': {f'{field}': {'$toLower': f'${field}'}},
# {'$group': {'_id': {f'{field}': f'${field}'},
'count': {'$sum': 1}}
},
{'$match': {'count': {'$gte': 2}}
},
{'$sort': {'count': -1}},
{'$out': f'{field}_counts2'}]
return self.aggregate(indeed_counts)
def indeed_double_count_aggregation(self, field1, field2):
indeed_value_counts = [
{'$match': {f'{field1}': {'$not': {'$size': 0}},
f'{field2}': {'$not': {'$size': 0}}}
},
{'$group': {'_id': {f'{field1}': {'$toLower': f'${field1}'},
f'{field2}': {'$toLower': f'${field2}'}},
'count': {'$sum': 1}}
},
{'$match': {'count': {'$gte': 2}}
},
{'$sort': {'count': -1}
},
{'$out': f'{field1}_{field2}_counts'}]
return self.aggregate(indeed_value_counts)
def shipped_agg(status):
complete_orders_agg = [
{
"$match" : {
"status" : {
"$in" : status
}
}
},
{
"$group" : {
"_id" : {
"in_num" : "$in_num",
'status': '$status',
"date" : {
"$dateToString" : {
"format" : "%Y-%m-%d",
"date" : "$date_submitted"
}
}
},
"totalAmount" : {
"$sum" : {
"$multiply" : [
"$order_price",
"$quantity"
]
}
},
"totalItems" : {
"$sum" : "$quantity"
},
"count" : {
"$sum" : 1.0
},
"order" : {
"$push" : "$$ROOT"
},
"shipto_ref": {"$addToSet": "$ship_ref._id"}
}
},
{
'$sort': {'_id.in_num': -1}
},
{
"$unwind" : {
"path" : "$order"
}
}
]
return complete_orders_agg
def address_in_production_agg():
agg = [
{
"$match" : {
"status" : {
"$nin" : [
"Cancelled",
"Complete"
]
}
}
},
{
"$project" : {
"_id" : 1.0,
"shipto_ref" : 1.0
}
},
{
"$group" : {
"_id" : "$shipto_ref",
"order" : {
"$push" : "$$ROOT"
}
}
},
{
"$addFields" : {
"item_count" : {
"$size" : "$order"
}
}
},
{
"$lookup" : {
"from" : "ShipTo",
"localField" : "_id",
"foreignField" : "_id",
"as" : "shipto"
}
},
{
"$unwind" : {
"path" : "$shipto"
}
}
]
return agg
get_dashboard_que = [
{
'$match': {
'status': {
'$nin': ['Complete', 'Cancelled', 'Shipped']
}
}
},
{
"$project" : {
"_id": 1.0,
"order_sku": 1.0,
"quantity": 1.0,
"quantity_fulfilled_count": 1.0
}
},
{
"$group" : {
"_id" : "$order_sku",
"total_qty_ordered": {"$sum" : "$quantity"},
"total_qty_filled": { "$sum" : "$quantity_fulfilled_count"}
}
},
{
'$sort': {'total_qty_ordered': -1}
}
]
agg_order_addresses = [
{
"$match" : {
"status" : {
"$nin" : [
"Cancelled",
"Complete"
]
}
}
},
{
"$group" : {
"_id" : "$shipto_ref",
"order" : {
"$push" : "$$ROOT"
}
}
},
{
"$lookup" : {
"from" : "ShipTo",
"localField" : "_id",
"foreignField" : "_id",
"as" : "shipto"
}
},
{
"$unwind" : {
"path" : "$shipto"
}
},
# {
# "$unwind" : {
# "path" : "$order"
# }
# },
# {
# "$lookup" : {
# "from" : "ShipTo",
# "localField" : "shipto_ref",
# "foreignField" : "_id",
# "as" : "shipto"
# }
# }
]
get_que_agg = [
{
'$match': {
'status': {
'$nin': ['Complete', 'Cancelled', 'Shipped']
}
}
},
{
"$project" : {
"_id": 1.0,
"order_sku": 1.0,
"quantity": 1.0,
"quantity_fulfilled_count": 1.0
}
},
{
"$group" : {
"_id" : "$order_sku",
"total_qty_ordered": {"$sum" : "$quantity"},
"total_qty_filled": { "$sum" : "$quantity_fulfilled_count"}
}
},
{
'$sort': {'total_qty_ordered': -1}
}
]
db.getCollection("Order2").aggregate(
// Pipeline
[
// Stage 1
{
$match: {
// enter query here
'status': { '$in': ['Shipped'] }
// 'status': { '$in': ['Cancelled', 'Complete', 'Shipped'] }
}
},
// Stage 2
{
$group: {
// _id: '$invoice_num',
_id: {'invoice_num': '$invoice_num',
// 'date': { $dateToString: { format: "%Y-%m-%d", date: "$date_submitted" } }
},
invoice_num: { $first: '$invoice_num'},
totalAmount: { $sum: { $multiply: [ "$order_price", "$quantity" ] } },
totalItems: { $sum: "$quantity" },
count: {'$sum': 1},
order: {'$push': '$$ROOT'},
}
},
// Stage 3
{
$unwind: {
path: '$order',
// includeArrayIndex: <string>, // optional
// preserveNullAndEmptyArrays: <boolean> // optional
}
},
]
);
db.collection.aggregate([
{
$group: { _id: { name: "$name", value: "$value" },
doc: { $last: "$$ROOT" } // Retrieve only last doc in a group
}
},
{
$replaceRoot: { newRoot: "$doc" } // replace doc as object as new root of document
},
{ $out : 'collection_new' } // Test above aggregation & then use this
])
or
You could group by _id via $group and then use the $last and $first operator respectively to keep the last or first values.
https://stackoverflow.com/questions/39315892/removing-duplicates-in-mongodb-with-aggregate-query
db.games.aggregate([
{
$unwind : "$rounds"
},
{
$match: {
"rounds.round_values.gameStage": "River",
"rounds.round_values.decision": "BetPlus"
}
},
{
$group: {
_id: "$_id",
"FinalFundsChange": { $first: "$FinalFundsChange" },
"GameID": { $last: "$GameID" }
}
}
])
[
{
'$match': {
'map_key': {
'$ne': None
}
}
}, {
'$project': {
'map_key': 1,
'Val.Text': 1
}
}, {
'$replaceRoot': {
'newRoot': {
'_id': '$_id',
'key': '$map_key',
'value': '$Val.Text'
}
}
}, {
'$group': {
'_id': {
'key': '$key',
'value': '$value'
},
'doc': {
'$push': '$$ROOT'
}
}
}
]
from pymongo import MongoClient
import urllib
uri = "mongodb+srv://<username>:" + urllib.parse.quote('<pass@!word>') + "@test1-43de3.asdasd.mongodb.net/test?retryWrites=true&w=majority"
client = pymongo.MongoClient(uri)
db = client.test
collection = db['db_name']
from pymongo import MongoClient
class Connect(object):
@staticmethod
def get_connection():
return MongoClient("mongodb://$[username]:$[password]@$[hostlist]/$[database]?authSource=$[authSource]")
cursor = db.inventory.find(
{"$or": [{"status": "A"}, {"qty": {"$lt": 30}}]})
cursor = db.inventory.find({"status": "A", "qty": {"$lt": 30}})
cursor = db.inventory.find({
"status": "A",
"$or": [{"qty": {"$lt": 30}}, {"item": {"$regex": "^p"}}]})
https://docs.mongodb.com/guides/server/update/#update-a-single-document-in-the-inventory-collection
To change a field value, MongoDB provides update operators to modify values. Some update operators, including will create the specified field if the field does not exist in the document.
The following operation updates the first document with item equal to paper.
The operation uses:
currentDateto set the
lastModified` field to the current date.
db.inventory.update_one(
{"item": "paper"},
{"$set": {"size.uom": "cm", "status": "P"},
"$currentDate": {"lastModified": True}})
loop = asyncio.get_event_loop()
loop.run_until_complete(do_update_one())
db.inventory.update_one(
{
"item": "paper"
},
{
"$set": {"size.uom": "cm", "status": "P"},
"$currentDate": {"lastModified": True}
}
)
ne
– not equal tolt
– less thanlte
– less than or equal togt
– greater thangte
– greater than or equal tonot
– negate a standard check, may be used before other operators (e.g.
Q(age__not__mod=(5, 0))
)in
– value is in list (a list of values should be provided)nin
– value is not in list (a list of values should be provided)mod
– value % x == y
, where x
and y
are two provided valuesall
– every item in list of values provided is in arraysize
– the size of the array isexists
– value for field existsexact
– string field exactly matches valueiexact
– string field exactly matches value (case insensitive)contains
– string field contains valueicontains
– string field contains value (case insensitive)startswith
– string field starts with valueistartswith
– string field starts with value (case insensitive)endswith
– string field ends with valueiendswith
– string field ends with value (case insensitive)match
– performs an $elemMatch so you can match an entire document within an arrayhttp://docs.mongoengine.org/guide/querying.html#atomic-updates
set
– set a particular valueunset
– delete a particular value (since MongoDB v1.3)inc
– increment a value by a given amountdec
– decrement a value by a given amountpush
– append a value to a listpush_all
– append several values to a listpop
– remove the first or last element of a list depending on the valuepull
– remove a value from a listpull_all
– remove several values from a listadd_to_set
– add value to a list only if its not in the list alreadyhttp://docs.mongoengine.org/guide/defining-documents.html?highlight=disk#indexes
Direction may be specified on fields by prefixing the field name with the following:
Note that direction only matters on multi-field indexes.
- +/- (for ascending) or a - sign (for descending).
- $ Text indexes may be specified by prefixing the field name with a $.
- # Hashed indexes may be specified by prefixing the field name with a #:
Example:
class Page(Document):
category = IntField()
title = StringField()
rating = StringField()
created = DateTimeField()
meta = {
'indexes': [
'title',
'$title', # text index
'#title', # hashed index
('title', '-rating'),
('category', '_cls'),
{
'fields': ['created'],
'expireAfterSeconds': 3600
}
]
}
class CustomerMaster(mondb.DynamicDocument):
customer = mondb.StringField()
name = mondb.StringField()
attn = mondb.StringField()
# start_date = mondb.StringField(nullable=True)
start_date = mondb.DateTimeField(nullable=True)
memo = mondb.StringField()
sales_rep = mondb.StringField()
notes = mondb.StringField()
phone = mondb.StringField()
fax = mondb.StringField()
address = mondb.StringField()
city = mondb.StringField()
meta = {
'indexes': [{
'fields': ['$**'],
'default_language': 'english',
'weights': {'customer': 1,
'name': 1,
'attn': 1,
'start_date': 1,
'memo': 1,
'sales_rep': 1,
'notes': 1,
'phone': 1,
'fax': 1,
'address': 1,
'city': 1}
}],
'allow_inheritance': False,
"ordering": ['start_date'],
'collection': 'CustomerMaster'}
http://docs.mongoengine.org/guide/defining-documents.html#dynamic-document-schemas
from mongoengine import *
class Page(DynamicDocument):
title = StringField(max_length=200, required=True)
# Create a new page and add tags
>>> page = Page(title='Using MongoEngine')
>>> page.tags = ['mongodb', 'mongoengine']
>>> page.save()
>>> Page.objects(tags='mongoengine').count()
>>> 1
http://docs.mongoengine.org/guide/defining-documents.html#one-to-many-with-listfields
If you are implementing a one to many relationship via a list of references, then the references are stored as DBRefs and to query you need to pass an instance of the object to the query:
class User(Document):
name = StringField()
class Page(Document):
content = StringField()
authors = ListField(ReferenceField(User))
bob = User(name="Bob Jones").save()
john = User(name="John Smith").save()
Page(content="Test Page", authors=[bob, john]).save()
Page(content="Another Page", authors=[john]).save()
# Find all pages Bob authored
Page.objects(authors__in=[bob])
# Find all pages that both Bob and John have authored
Page.objects(authors__all=[bob, john])
# Remove Bob from the authors for a page.
Page.objects(id='...').update_one(pull__authors=bob)
# Add John to the authors for a page.
Page.objects(id='...').update_one(push__authors=john)
http://docs.mongoengine.org/guide/defining-documents.html#indexes
You can specify indexes on collections to make querying faster. This is done by creating a list of index specifications called indexes in the meta dictionary, where an index specification may either be a single field name, a tuple containing multiple field names, or a dictionary containing a full index definition.
A direction may be specified on fields by prefixing the field name with a + (for ascending) or a - sign (for descending). Note that direction only matters on multi-field indexes. Text indexes may be specified by prefixing the field name with a $. Hashed indexes may be specified by prefixing the field name with a #:
fields (Default: None)
The fields to index. Specified in the same format as described above.
cls (Default: True)
If you have polymorphic models that inherit and have allow_inheritance turned on, you can configure whether the index should have the _cls field added automatically to the start of the index.
sparse (Default: False)
Whether the index should be sparse.
unique (Default: False)
Whether the index should be unique.
expireAfterSeconds (Optional)
Allows you to automatically expire data from a collection by setting the time in seconds to expire the a field.
name (Optional)
Allows you to specify a name for the index
collation (Optional)
Allows to create case insensitive indexes (MongoDB v3.4+ only)
class Page(Document):
category = IntField()
title = StringField()
rating = StringField()
created = DateTimeField()
meta = {
'indexes': [
'title',
'$title', # text index
'#title', # hashed index
('title', '-rating'),
('category', '_cls'),
{
'fields': ['created'],
'expireAfterSeconds': 3600
}
]
}
http://docs.mongoengine.org/guide/defining-documents.html#document-inheritance
# Stored in a collection named 'page'
class Page(Document):
title = StringField(max_length=200, required=True)
meta = {'allow_inheritance': True}
# Also stored in the collection named 'page'
class DatedPage(Page):
date = DateTimeField()
class MShipTo(mondb.DynamicDocument):
is_default_shipto = mondb.StringField(nullable=False, default='Not Default')
name = mondb.StringField(nullable=True)
company_name = mondb.StringField(nullable=True)
unit_number = mondb.StringField(nullable=False)
street_name = mondb.StringField(nullable=False)
street_type = mondb.StringField(nullable=False)
city_name = mondb.StringField(nullable=False)
state_province = mondb.StringField(nullable=False)
country = mondb.StringField(nullable=False)
zip_code = mondb.StringField(nullable=False)
tax_shipping_code = mondb.StringField()
phone = mondb.StringField(nullable=True)
email = mondb.StringField(nullable=True)
other_customer_info = mondb.StringField()
created_on = mondb.DateTimeField(nullable=False, default=default_time)
invoice_address = mondb.StringField(nullable=False)
checkout_address = mondb.StringField(nullable=False)
meta = {'collection': 'ShipTo'}
class OrderShipTo(DynamicEmbeddedDocument):
name = mondb.StringField(nullable=True)
company_name = mondb.StringField(nullable=True)
unit_number = mondb.StringField(nullable=False)
street_name = mondb.StringField(nullable=False)
street_type = mondb.StringField(nullable=False)
city_name = mondb.StringField(nullable=False)
state_province = mondb.StringField(nullable=False)
country = mondb.StringField(nullable=False)
zip_code = mondb.StringField(nullable=False)
tax_shipping_code = mondb.StringField()
phone = mondb.StringField(nullable=True)
email = mondb.StringField(nullable=True)
other_customer_info = mondb.StringField()
invoice_address = mondb.StringField()
meta = {'collection': 'OrderShipTo'}
Insert Data
_ship_addr = MShipTo.objects.get(id=d['shipto'])
ship_addr_embed = OrderShipTo(
name=_ship_addr.name,
company_name=_ship_addr.company_name,
unit_number=_ship_addr.unit_number,
street_name=_ship_addr.street_name,
street_type=_ship_addr.street_type,
city_name=_ship_addr.city_name,
state_province=_ship_addr.state_province,
zip_code=_ship_addr.zip_code,
tax_shipping_code=_ship_addr.tax_shipping_code,
phone=_ship_addr.phone,
email=_ship_addr.email,
invoice_address=_ship_addr.invoice_address,
other_customer_info=_ship_addr.other_customer_info)
Query
s = MOrder.objects(status="In Production",
address_embed__name=person_name,
address_embed__company_name=company_name,
address_embed__unit_number=unit_num,
address_embed__zip_code=zip_code).all()
http://docs.mongoengine.org/guide/defining-documents.html#abstract-classes
If you want to add some extra functionality to a group of Document classes but you don’t need or want the overhead of inheritance you can use the abstract attribute of meta.
This won’t turn on Document inheritance but will allow you to keep your code DRY:
class BaseDocument(Document):
meta = {
'abstract': True,
}
def check_permissions(self):
pass
class User(BaseDocument):
pass
http://docs.mongoengine.org/guide/querying.html#retrieving-a-subset-of-fields
Sometimes a subset of fields on a Document is required, and for efficiency only these should be retrieved from the database.
This issue is especially important for MongoDB, as fields may often be extremely large (e.g. a ListField of EmbeddedDocuments, which represent the comments on a blog post.
To select only a subset of fields, use only(), specifying the fields you want to retrieve as its arguments. Note that if fields that are not downloaded are accessed, their default value (or None if no default value is provided) will be given:
The exclude() is the opposite of only() if you want to exclude a field.
>>> class Film(Document):
... title = StringField()
... year = IntField()
... rating = IntField(default=3)
...
>>> Film(title='The Shawshank Redemption', year=1994, rating=5).save()
>>> f = Film.objects.only('title').first()
>>> f.title
'The Shawshank Redemption'
>>> f.year # None
>>> f.rating # default value
3
http://docs.mongoengine.org/guide/querying.html#getting-related-data
When iterating the results of ListField or DictField we automatically dereference any DBRef objects as efficiently as possible, reducing the number the queries to mongo.
There are times when that efficiency is not enough, documents that have ReferenceField objects or GenericReferenceField objects at the top level are expensive as the number of queries to MongoDB can quickly rise.
To limit the number of queries use select_related() which converts the QuerySet to a list and dereferences as efficiently as possible. By default select_related() only dereferences any references to the depth of 1 level.
If you have more complicated documents and want to dereference more of the object at once then increasing the max_depth will dereference more levels of the document.
It is possible to order the results by 1 or more keys using order_by()
.
The order may be specified by prepending each
of the keys
by “+” or “-”
.
Ascending order is assumed if there’s no prefix.
blogs = BlogPost.objects().order_by('date') # equivalent to .order_by('+date')
blogs = BlogPost.objects().order_by('+date', '-title')
Using only makes your query efficient.
Extract only specified data.
>>> class Film(Document):
... title = StringField()
... year = IntField()
... rating = IntField(default=3)
...
>>> Film(title='The Shawshank Redemption', year=1994, rating=5).save()
>>> f = Film.objects.only('title').first()
>>> f.title
'The Shawshank Redemption'
>>> f.year # None
>>> f.rating # def
Just as with limiting and skipping results, there is a method on a QuerySet object – count():
num_users = User.objects.count()
You may sum over the values of a specific field on documents using sum():
yearly_expense = Employee.objects.sum('salary')
http://docs.mongoengine.org/guide/querying.html#further-aggregation
To get the average (mean) of a field on a collection of documents, use average():
mean_age = User.objects.average('age')
As MongoDB provides native lists, MongoEngine provides a helper method to get a dictionary of the frequencies of items in lists across an entire collection.
An example of its use would be generating “tag-clouds”:
class Article(Document):
tag = ListField(StringField())
#After adding some tagged articles...
tag_freqs = Article.objects.item_frequencies('tag', normalize=True)
from operator import itemgetter
top_tags = sorted(tag_freqs.items(), key=itemgetter(1), reverse=True)[:10]
http://docs.mongoengine.org/guide/querying.html#getting-related-data
Sometimes calling a QuerySet object with keyword arguments can’t fully express the query you want to use – for example if you need to combine a number of constraints using and and or.
This is made possible in MongoEngine through the Q class.
A Q object represents part of a query, and can be initialised using the same keyword-argument syntax you use to query documents.
To build a complex query, you may combine Q objects using the & (and) and | (or) operators.
To use a Q object, pass it in as the first positional argument to Document.objects when you filter it by calling it with keyword arguments:
You have to use bitwise operators.
You cannot use or, and to combine queries as Q(a=a)
or Q(b=b)
is not the same as Q(a=a) | Q(b=b)
.
As Q(a=a)
equates to true Q(a=a)
or Q(b=b)
is the same as Q(a=a)
.
from mongoengine.queryset.visitor import Q
# Get published posts
Post.objects(Q(published=True) | Q(publish_date__lte=datetime.now()))
# Get top posts
Post.objects((Q(featured=True) & Q(hits__gte=1000)) | Q(hits__gte=5000))
https://stackoverflow.com/questions/36565086/query-embedded-document-list-in-mongoengine
class Variant(EmbeddedDocument):
name = StringField(required=True)
value = StringField(required=True)
class Sku(Document):
variants = ListField(EmbeddedDocumentField(Variant))
Actually you were doing it "incorrectly" in the shell as well.
The format you were using requires an exact match that would "rarely" actually match conditions.
It certainly would not should the inner keys of the array be stored in a different order, or most importantly that the array itself actually stored more than one element.
The correct form for the "shell" would be:
db.sku.find({ "variants": { "$elemMatch": { "name": "xxx", "value": "xxx" } } })
By the same token, the "correct" form for MongoEngine is:
Sku.objects(variants__match={ "name": "xxx", "value": "xxx" })
The __match construct here is the same thing as, and actually issues an $elemMatch statement in query to the underlying MongoDB database as a query.
Note that for a "single" element condition the general "double underscore" syntax is just fine:
Sku.objects(variants__name="xxx")
But for "multiple" conditions and/or elements within the array/list, you need $elemMatch
as a MongoDB query and therefore __match
.
http://docs.mongoengine.org/guide/querying.html#atomic-updates
set
– set a particular valueunset
– delete a particular value (since MongoDB v1.3)inc
– increment a value by a given amountdec
– decrement a value by a given amountpush
– append a value to a listpush_all
– append several values to a listpop
– remove the first or last element of a list depending on the valuepull
– remove a value from a listpull_all
– remove several values from a listadd_to_set
– add value to a list only if its not in the list alreadyDocuments may be updated atomically by using the update_one(), update() and modify() methods on a QuerySet or modify() and save() (with save_condition argument) on a Document.
There are several different “modifiers” that you may use with these methods:
The syntax for atomic updates is similar to the querying syntax, but the modifier comes before the field, not after it:
>>> post = BlogPost(title='Test', page_views=0, tags=['database'])
>>> post.save()
>>> BlogPost.objects(id=post.id).update_one(inc__page_views=1)
>>> post.reload() # the document has been changed, so we need to reload it
>>> post.page_views
>>> BlogPost.objects(id=post.id).update_one(set__title='Example Post')
>>> post.reload()
>>> post.title
'Example Post'
BlogPost.objects(id=post.id).update_one(push__tags='nosql')
post.reload()
post.tags
['database', 'nosql']
If no modifier operator is specified the default will be $set. So the following sentences are identical:
BlogPost.objects(id=post.id).update(title='Example Post')
BlogPost.objects(id=post.id).update(set__title='Example Post')
The positional operator allows you to update list items without knowing the index position, therefore making the update a single atomic operation.
As we cannot use the $ syntax in keyword arguments it has been mapped to S:
post = BlogPost(title='Test', page_views=0, tags=['database', 'mongo'])
post.save()
BlogPost.objects(id=post.id, tags='mongo').update(set__tags__S='mongodb')
post.reload()
post.tags
['database', 'mongodb']
From MongoDB version 2.6, push operator supports $position value which allows to push values with index:
post = BlogPost(title="Test", tags=["mongo"])
post.save()
post.update(push__tags__0=["database", "code"])
post.reload()
post.tags
['database', 'code', 'mongo']
https://docs.mongodb.com/manual/tutorial/control-results-of-text-search/
http://docs.mongoengine.org/guide/text-indexes.html#text-search
class News(Document):
title = StringField()
content = StringField()
is_active = BooleanField()
meta = {'indexes': [
{'fields': ['$title', "$content"],
'default_language': 'english',
'weights': {'title': 10, 'content': 2}
}
]}
The text index has the following fields and weights:
content has a weight of 10,
keywords has a weight of 5, and
about has the default weight of 1.
These weights denote the relative significance of the indexed fields to each other. For instance, a term match in the content field has:
2 times (i.e. 10:5) the impact as a term match in the keywords field and
10 times (i.e. 10:1) the impact as a term match in the about field.
https://docs.mongodb.com/manual/core/index-wildcard/#create-a-wildcard-index-on-all-fields
To index the value of all fields in a document (excluding _id), specify "$**" as the index key:
With this wildcard index, MongoDB indexes all fields for each document in the collection. If a given field is a nested document or array, the wildcard index recurses into the document/array and stores the value for all fields in the document/array.
Wildcard indexes omit the _id field by default. To include the _id field in the wildcard index, you must explicitly include it in the wildcardProjection document. See Options for wildcard indexes for more information.
https://www.tutorialspoint.com/mongodb/mongodb_autoincrement_sequence.htm
function getNextSequenceValue(sequenceName) {
var sequenceDocument = db.counters.findAndModify({
query:{_id: sequenceName },
update: {$inc:{sequence_value:1}},
new:true
});
return sequenceDocument.sequence_value;
}
https://www.mongodb.com/docs/manual/reference/sql-comparison/#create-and-alter
SQL Schema Statements | MongoDB Schema Statements | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Implicitly created on first
However, you can also explicitly create a collection:
| ||||||||||||||
| Collections do not describe or enforce the structure of its documents; i.e. there is no structural alteration at the collection level. However, at the document level,
| ||||||||||||||
| Collections do not describe or enforce the structure of its documents; i.e. there is no structural alteration at the collection level. However, at the document level,
| ||||||||||||||
|
| ||||||||||||||
|
| ||||||||||||||
|
|
SQL SELECT Statements | MongoDB find() Statements | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
| ||||||||
|
| ||||||||
|
| ||||||||
|
| ||||||||
|
| ||||||||
|
| ||||||||
|
| ||||||||
|
| ||||||||
|
| ||||||||
|
| ||||||||
|
| ||||||||
|
-or-
| ||||||||
|
-or-
| ||||||||
|
| ||||||||
|
| ||||||||
|
or
| ||||||||
|
or
| ||||||||
|
or
| ||||||||
|
or, for distinct value sets that do not exceed the BSON size limit
| ||||||||
|
or
| ||||||||
|
| ||||||||
|
|