能否无Schema使用NDB库?Datastore客户端与NDB的差异咨询
Absolutely! While NDB is primarily built for structured, predefined models (as you pointed out), it does support schema-less operations using the ndb.Expando class instead of the standard ndb.Model. Here's how to make it work:
Using ndb.Expando for flexible schema-less operations
Expando is a subclass of Model that lets you add arbitrary properties to entities without predefining them in the class. This gives you the raw Datastore client's flexibility while keeping NDB's perks like caching, async operations, and key management.
Example: Putting a schema-less entity
from google.cloud import ndb class Test(ndb.Expando): # No predefined properties required pass # Create an entity with any properties you want test_entity = Test(foo="foo", bar="bar", xxx="xxx", custom_prop="whatever value") # Save it to Datastore test_entity.put()
Example: Retrieving and working with arbitrary properties
# Fetch the entity back from Datastore fetched_entity = test_entity.key.get() # Access properties directly, even those not predefined print(fetched_entity.bar) # Output: "bar" print(fetched_entity.custom_prop) # Output: "whatever value" # You can even add new properties dynamically after fetching fetched_entity.new_dynamic_prop = "fresh value" fetched_entity.put()
Mixing structured and schema-less properties (optional)
If you want some predefined properties (with validation, indexing rules, etc.) plus the ability to add arbitrary ones, you can combine ndb.Model with ndb.GenericProperty, but Expando is simpler for fully schema-less use cases. Here's a quick example:
class MixedTest(ndb.Model): # Predefined property with strict settings required_foo = ndb.StringProperty(required=True) # Allow any additional properties extra_props = ndb.GenericProperty()
Key notes to keep in mind
- Querying arbitrary properties: When querying for properties that aren't predefined, you can reference them directly in your query (NDB handles this dynamically with
Expando):# Fetch all entities where xxx equals "xxx" results = Test.query(Test.xxx == "xxx").fetch() - Trade-offs: Using
Expandomeans you lose the type safety and validation that comes with predefined properties. If you need strict schema enforcement for parts of your app, stick tondb.Model. But for flexible, schema-less scenarios,Expandois perfect.
So to wrap up: You don't have to ditch NDB for schema-less operations—just swap ndb.Model with ndb.Expando and you're good to go.
内容的提问来源于stack exchange,提问作者stack_user

