问题
I want to know how to use MongoAlchemy about embeded docment operation. But I havn't find any documents about these. Can anyone give me some helps?
Here is demo code:
#!/usr/bin/python
# -*- coding: utf-8 -*-
from flask import Flask
from flaskext.mongoalchemy import MongoAlchemy
app = Flask(__name__)
app.config['DEBUG'] = True
app.config['MONGOALCHEMY_DATABASE'] = 'book'
db = MongoAlchemy(app)
class Comment(db.Document):
user_id = db.StringField(db_field='uid')
posted = db.StringField(db_field='posted')
class Book(db.Document):
title = db.StringField()
author = db.StringField()
comments = db.ListField(db.DocumentField(Comment), db_field='Comments')
from mongoalchemy.session import Session
def test():
with Session.connect('book') as s:
s.clear_collection(Book)
save()
test_Book()
def save():
title = "Hello World"
author = 'me'
comment_a = Comment(user_id='user_a', posted='post_a')
comment_b = Comment(user_id='user_b', posted='post_b')
comments = [comment_a, comment_b]
book = Book(title=title, author=author, comments=comments)
book.save()
def test_Book():
book = Book.query.filter({'author':'me'}).first()
comment = book.comments[0]
comment.posted = str(book.comments[0].posted)+'_new'
book.save()
print 'change posted: Book.comments[0].posted:', book.comments[0].posted
comment_c = Comment(user_id='user_c', posted='post_c')
book.comments.append(comment_c)
book.save()
print 'append: Book.comments[2].posted:', book.comments[2].posted
query = Book.query.filter({Book.comments:{'$elemMatch':{Comment.user_id:'user_c'}}}).limit(1).first()
print 'query type:', type(query)
if __name__ == '__main__':
test()
I want to query data which user_id is "user_c", and just return back one Comment, How can I do that? Does these methods below are MongoAlchemy remommended? BTW, these methods will return the whole document.
#query = Book.query.filter({Book.comments:{'uid':'user_c'}}).limit(1).first() #query = Book.query_class(Comment).filter(Comment.user_id == 'user_c').limit(1).first() #query = Book.query.filter({'comments':{'$elemMatch':{'uid':'user_c'}}}).limit(1).first() #query = Book.query.filter({Book.comments:{'$elemMatch':{Comment.user_id:'user_c'}}}).limit(1).first()
How can I change "user_c" to "user_c_new" which find by query ?
- How can I remove one comment which user_id is "user_b"?
回答1:
Mongo doesn't support returning subdocuments. You can use $elemMatch to filter so that only documents with matching attributes are returned, but you'll have to grab the comments yourself. You could slightly optimize by only returning the comments field as follows:
query = Book.query.filter({Book.comments:{'$elemMatch':{Comment.user_id:'user_c'}}})
query = query.fields(Book.comments.elem_match({Comment.user_id:'user_c'}))
result = query.limit(1).first()
print 'query result:', result.comments
Note that there was a bug with this up until 0.14.3 (which I just released a few minutes ago) which would have caused results.comments not to work.
Another very important note is that the elem_match I'm doing there only returns the first matching element. If you want all matching elements you have to filter them yourself:
query = Book.query.filter({Book.comments:{'$elemMatch':{Comment.user_id:'user_c'}}})
result = query.limit(1).first()
print 'query result:', [c for c in result.comments if c.user_id == 'user_c']
来源:https://stackoverflow.com/questions/20265271/mongoalchemy-query-embedded-documents