NDB Library for Google Cloud Datastore
google-cloud-ndb is a Python client library for Google Cloud Datastore, providing an ORM-like interface for interacting with the service. It is a modern, standalone re-implementation of the original App Engine NDB. The current version is 2.4.2, and it is part of the larger `google-cloud-python` monorepo, which has frequent releases, though individual library updates may be less frequent.
Warnings
- breaking Migration from original App Engine NDB (`google.appengine.ext.ndb`) to `google-cloud-ndb` requires significant code changes. This library is a standalone client for Cloud Datastore, not a drop-in replacement for App Engine apps. Key differences include package name (`google.cloud.ndb`), mandatory `async/await` for most operations, and different client initialization and context management.
- gotcha All NDB database operations (e.g., `put()`, `get()`, `fetch()`) are asynchronous and return 'futures'. Forgetting to `await` these operations will result in the operation not being executed or incorrect data being returned (the future object itself, not its result).
- gotcha All Datastore interactions must occur within an NDB context. Failing to establish a context will raise a `RuntimeError: A context is required for this operation.`
- gotcha This library requires Python 3.9 or newer. It is not compatible with Python 2.7 or older Python 3 versions.
- gotcha When developing locally, `google-cloud-ndb` will attempt to connect to a live Datastore instance unless `DATASTORE_EMULATOR_HOST` environment variable is explicitly set to point to a running Datastore emulator. This can lead to unintended writes to your production database if not careful.
Install
-
pip install google-cloud-ndb
Imports
- ndb
from google.cloud import ndb
- Client
from google.cloud.ndb import Client
- Model
from google.cloud.ndb import Model
Quickstart
import os
from google.cloud import ndb
import asyncio
# For local development, point to the Datastore emulator
# Ensure you've started the emulator: `gcloud emulators datastore start`
# os.environ['DATASTORE_EMULATOR_HOST'] = 'localhost:8081'
# Replace with your actual project ID or ensure GOOGLE_CLOUD_PROJECT env var is set
project_id = os.environ.get('GOOGLE_CLOUD_PROJECT', 'your-gcp-project-id')
class User(ndb.Model):
name = ndb.StringProperty()
email = ndb.StringProperty()
created = ndb.DateTimeProperty(auto_now_add=True)
async def main():
# The NDB client is typically created once per application lifecycle
client = ndb.Client(project=project_id)
# All Datastore operations must happen within a context
async with client.context():
# Create a new user entity
user = User(name='Alice', email='alice@example.com')
user_key = await user.put()
print(f'Created user with key: {user_key.id()}')
# Fetch the user back by key
fetched_user = await user_key.get_async()
if fetched_user:
print(f'Fetched user: {fetched_user.name} ({fetched_user.email})')
# Query for users
query = User.query(User.name == 'Alice')
users_with_name = await query.fetch_async(limit=1)
if users_with_name:
print(f'Query result: {users_with_name[0].name}')
# Update a user
fetched_user.email = 'alice.new@example.com'
await fetched_user.put()
print(f'Updated user email to: {fetched_user.email}')
# Delete a user
await user_key.delete_async()
print(f'Deleted user with key: {user_key.id()}')
if __name__ == '__main__':
asyncio.run(main())