我正在用猫鼬构建一个node.js应用程序,但是我目前正试图尝试正确查询MongoDB ...
我目前有3种MongoDB模型:
admin/Manage
1个房间多排,1个座位多排。
我可以使用以下查询来获取包含所有行的Room对象:
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import ctypes
import ctypes.wintypes
user32 = ctypes.windll.user32
HUD_WIDTH = 100
HUD_HEIGHT = 50
WINDOW_NAME = "Window name" #Replace this by the name of an opened window
EVENT_OBJECT_LOCATIONCHANGE = 0x800B
EVENT_SYSTEM_FOREGROUND = 0x0003
WINEVENT_OUTOFCONTEXT = 0x0000
EVENT_SYSTEM_MINIMIZEEND = 0x0017
class Hud(QLabel):
def __init__(self,window_handle):
super().__init__()
self.initUI()
self.window_handle = window_handle
rect = ctypes.wintypes.RECT()
user32.GetWindowRect(window_handle,ctypes.byref(rect))
self.window_x = rect.left
self.window_y = rect.top
self.setFollowWindow()
def initUI(self):
self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint)
self.resize(HUD_WIDTH,HUD_HEIGHT)
p = self.palette()
p.setColor(self.backgroundRole(), Qt.black)
p.setColor(self.foregroundRole(),Qt.white)
self.setPalette(p)
self.setWindowOpacity(0.7)
self.setText("Hello")
self.setAlignment(Qt.AlignCenter)
self.show()
def mousePressEvent(self,event):
self.click_x_coordinate = event.x()
self.click_y_coordinate = event.y()
def mouseMoveEvent(self,event):
self.move(event.globalX()-self.click_x_coordinate,event.globalY()-self.click_y_coordinate)
def setFollowWindow(self):
WinEventProcType = ctypes.WINFUNCTYPE(
None,
ctypes.wintypes.HANDLE,
ctypes.wintypes.DWORD,
ctypes.wintypes.HWND,
ctypes.wintypes.LONG,
ctypes.wintypes.LONG,
ctypes.wintypes.DWORD,
ctypes.wintypes.DWORD
)
def callback(hWinEventHook, event, hwnd, idObject, idChild, dwEventThread, dwmsEventTime):
if idObject != -9: #Avoids mouse events
if event == EVENT_OBJECT_LOCATIONCHANGE and hwnd == self.window_handle:
rect = ctypes.wintypes.RECT()
user32.GetWindowRect(hwnd,ctypes.byref(rect))
self.move(self.x() + rect.left - self.window_x,self.y() + rect.top - self.window_y)
self.window_x = rect.left
self.window_y = rect.top
elif event == EVENT_SYSTEM_FOREGROUND or event == EVENT_SYSTEM_MINIMIZEEND:
if hwnd == self.window_handle:
user32.SetWindowPos(self.winId().__int__(),-1,self.x(),self.y(),self.width(),
self.height())
self.WinEventProc = WinEventProcType(callback)
user32.SetWinEventHook.restype = ctypes.wintypes.HANDLE
self.hook = user32.SetWinEventHook(
EVENT_SYSTEM_FOREGROUND,
EVENT_OBJECT_LOCATIONCHANGE,
0,
self.WinEventProc,
0,
0,
WINEVENT_OUTOFCONTEXT
)
class MainWindow(QMainWindow):
def __init__(self):
super(MainWindow,self).__init__()
self.initUI()
def initUI(self):
self.launch_hud_button = QPushButton("Launch HUD",self)
self.launch_hud_button.clicked.connect(self.launchHud)
self.show()
def launchHud(self):
window_handle = user32.FindWindowW(0,WINDOW_NAME)
if window_handle != 0 :
self.hud = Hud(window_handle)
if __name__ == '__main__':
app = QApplication(sys.argv)
main_window = MainWindow()
sys.exit(app.exec_())
但是,我找不到用于获取每一行席位的解决方案,异步处理正在破坏每次尝试的逻辑。 我已经尝试过for循环,async.waterfall(),Promise.all(),但我每次都失败。
有人烦我吗?谢谢!
备注:如评论和可能的答案中所建议,我应该仅使用一种模型,我已经拥有那种模型,但是在更新多个席位时遇到了问题。将对此进行进一步的研究。
答案 0 :(得分:0)
通过正确设置引用ref
并稍微修改模型,您可以更轻松地实现此目的。但是,我将修改您的代码以向您展示如何按照您的方法进行操作,然后在引用字段中提供一个关于猫鼬填充的示例:
在进入代码之前,我将用.toObject()
替换文档上的.lean()
调用,这是一种猫鼬方法,它在查询文档并优化查询后为您执行此操作,因为它跳过了将MongoDB原始文档转换为Mongoose对象的过程:
// Encapsulate this with try-catch
const room = await Room.findOne({ name: req.params.room_name }, { __v: 0 }).lean().exec()
const rows = await Row.find({ roomid: room._id }, { roomid: 0, __v: 0 }).lean().exec()
// This is a blocking loop
for (let row of rows) {
const seats = await Seat.find({ rowid: row._id }, { rowid:0, __v: 0 }).lean().exec()
row.seats = seats
}
room.rows = rows
res.json(room)
// Close try-catch
现在可以使用Promise.all()
对for循环进行一些优化,它将异步执行每个循环迭代:
await Promises.all(rows.map(async (row) => {
const seats = await Seat.find({ rowid: row._id }, { rowid:0, __v: 0 }).lean().exec()
row.seats = seats
})
让我们通过直接简单地自然而然的推理来重新定义您的模型:
1个房间有很多行
然后,您可能希望您的房间具有一系列的行ID,如下所示:
const roomModel = mongoose.model('Room', new mongoose.Schema({
name: String,
rows: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Row'
}]
))
进一步
一排有很多座位
const rowModel = mongoose.model('Row', new mongoose.Schema({
seats: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Seat'
}],
name: String
))
最后,您的座位模型将非常简单:
const seatModel = mongoose.model('Seat', new mongoose.Schema({
position: Number,
number: Number
))
现在查询简单得多:
const room = await Room.findOne({ name: req.params.room_name }, { __v: 0 })
.populate({
path: 'rows',
select: '-__v', // Remove __v field
populate: {
path: 'seats',
select: '-__v' // Remove __v field
}).lean().exec()
res.json(room)
如您所见,采用这种方法并正确设计数据模型,可以更简单。 但是,这还不是您希望在MongoDB中设计数据模型的方式,如Neill Lunn在评论中所述。与其定义3个简单的数据模型,不如只定义1个模型,其中包含行和席位模式的嵌入式子文档数组。与此类似:
mongoose.model('Room', new mongoose.Schema({
name: String,
rows: [{
name: String,
seats: [{
position: Number,
number: Number,
}]
})