Ответ 1
Запрос этой структуры для желаемых результатов невозможен без предварительного уведомления всех возможных имен forms
и использования их в запросе. Во всяком случае, это было бы очень грязно. Тем не менее, читайте дальше, объясняя, как это можно сделать.
Существует проблема со структурой этих документов, которая будет препятствовать проведению разумного анализа запросов. В этом случае вам нужно будет знать все возможные поля имени формы, чтобы отфильтровывать что-либо.
В вашей текущей структуре есть формы, содержащие поддокумент, из которых каждый ключ содержит другой под-документ с единственным свойством, status
. Это трудно выполнить, поскольку ваш элемент forms
имеет произвольную структуру для каждого создаваемого вами документа. Это означает, что шаблон спускается к status
информации, которую вы хотите сравнить с изменениями для каждого документа в вашей коллекции.
Вот что я имею в виду по пути. Чтобы получить статус в любом элементе, вам необходимо выполнить следующие действия
Формы → PreOp → статус
Формы → Оповещение → статус
При повторном изменении второго элемента. Существует no way, чтобы подстановить что-то вроде этого, поскольку именование считается явным.
Это, возможно, считалось простым способом реализации сериализации данных из ваших форм, но я вижу альтернативу более гибкая. Вам нужна структура документа, которую вы можете перемещать по стандартной схеме. Это всегда стоит рассматривать в дизайне. Возьмите следующее:
{
"_id" : "Tvq444454j",
"name": "Jim",
"forms": [
{
"name": "Jorney",
"status":"closed"
},
{
"name": "Women",
"status":"void"
},
{
"name": "Child",
"status":"closed"
},
{
"name": "Farm",
"status":"closed"
}
]
}
Таким образом, структура документа изменяется, чтобы сделать элемент forms
массивом, а вместо того, чтобы поместить поле состояния под ключ, который называет "поле формы", мы имеем каждый член массива в качестве поддокумента обозначая "поле формы" name
и status
. Таким образом, и идентификатор, и статус все еще соединены вместе, но представлены только как суб-документ. Это наиболее важно изменяет путь доступа к этим ключам, так как теперь для и имя поля и его статус мы можем сделать
Формы → статус
или
Формы → имя
Что означает этот, так это то, что вы можете запросить, чтобы найти имена всех полей в form
или всех status
в form
или даже всех документах с определенное поле name
и некоторые status
. Это намного лучше, чем можно было бы сделать с исходной структурой.
Теперь в вашем конкретном случае вы хотите получить только документы, где все, поля не void
. Теперь в одном запросе нет способа сделать это, так как нет никакого оператора для сравнения всех элементов в массиве таким образом и посмотреть, являются ли они одинаковыми. Но есть два подхода, которые вы можете предпринять:
Первый и, вероятно, не столь эффективный запрос к всем документам, содержащим элемент в forms
, который имеет status
of void. С полученным идентификатором документа вы можете выдать другой запрос, который возвращает документы, у которых не есть указанный идентификатор.
db.forms.find({ "forms.status": "void" },{ _id: 1})
db.forms.find({ _id: $not: { $in: [<Object1>,<Object2>,<Object3>,... ] } })
Данный размер результата может быть невозможен, и обычно это не очень хорошо, поскольку оператор исключения $not
в основном заставляет полностью сканировать коллекцию, поэтому вы не можете использовать индекс.
Другой подход заключается в использовании конвейера агрегации следующим образом:
db.forms.aggregate([
{ "$unwind": "$forms" },
{ "$group": { "_id": "$_id", "status": { "$addToSet": "$forms.status" }}},
{ "$unwind": "$status" },
{ "$sort": { "_id": 1, "status": -1 }},
{ "$group": { "_id": "$_id", "status": { "$first": "$status"}}},
{ "$match":{ "status": "closed" }}
])
Конечно, это приведет только к возврату _id для документов, которые соответствуют, но вы можете отправить запрос с помощью $in и вернуть все соответствующие документы. Это лучше, чем оператор исключения, используемый ранее, и теперь мы можем использовать индекс, чтобы избежать полного сканирования коллекции.
В качестве окончательного подхода и для оценки эффективности наилучшего вы можете снова изменить документ, чтобы на верхнем уровне вы сохраняли "статус" того, будет ли какое-либо поле в формах "пусто", или "закрыто". Таким образом, на верхнем уровне значение будет закрыто только в том случае, если все элементы были "закрыты" и "недействительны", если что-то было недействительным и т.д.
Этот последний будет означать дальнейшее изменение программы, и все изменения в элементах forms
должны будут обновить это поле, а также сохранить "статус". Тем не менее, это самый эффективный способ найти нужные вам документы и заслуживает рассмотрения.
ИЗМЕНИТЬ
Помимо изменения документа для получения статуса мастера, самая быстрая форма запроса на пересмотренной структуре на самом деле:
db.forms.find({ "forms": { "$not": { "$elemMatch": { "status": "void" } } } })