Агрегат вложенного массива, принимающий только одно поле для сопоставления

У меня есть следующие данные json в mongodb.

[
  {
    "_id": 1,
    "name": "user1",
    "userActivities": [
      {
        "actionTaken": "Sign in.",
        "progress": "Success."
      },
      {
        "actionTaken": "logout",
        "progress": "Success."
      }
    ]
  },
  {
    "_id": 2,
    "name": "user2",
    "userActivities": [
      {
        "actionTaken": "Sign in.",
        "progress": "Success."
      },
      {
        "actionTaken": "logout",
        "progress": "Success."
      }
    ]
  },
  {
    "_id": 3,
    "name": "user3",
    "userActivities": [
      {
        "actionTaken": "Sign in.",
        "progress": "Success."
      },
      {
        "actionTaken": "logout",
        "progress": "Success."
      }
    ]
  },
  {
    "_id": 4,
    "name": "user4",
    "userActivities": [
      {
        "actionTaken": "Sign in.",
        "progress": "Success."
      },
      {
        "actionTaken": "logout",
        "progress": "Success."
      }
    ]
  },
  {
    "_id": 5,
    "name": "user5",
    "userActivities": [
      {
        "actionTaken": "Sign in.",
        "progress": "Success."
      },
      {
        "actionTaken": "logout",
        "progress": "Success."
      }
    ]
  },
  {
    "_id": 6,
    "name": "user6",
    "userActivities": [
      {
        "actionTaken": "Sign in.",
        "progress": "Success."
      },
      {
        "actionTaken": "logout",
        "progress": "Success."
      }
    ]
  },
  {
    "_id": 7,
    "name": "user7",
    "userActivities": [
      {
        "actionTaken": "Sign in.",
        "progress": "Success."
      },
      {
        "actionTaken": "logout",
        "progress": "Success."
      }
    ]
  },
  {
    "_id": 8,
    "name": "user8",
    "userActivities": [
      {
        "actionTaken": "Sign in.",
        "progress": "Success."
      },
      {
        "actionTaken": "logout",
        "progress": "Success."
      }
    ]
  }
]

Я запрашиваю данные для разбиения на страницы следующим образом.

[
    {
        "$match": {
            "userActivities": {
                "actionTaken": "Sign in."
            }
        }
    },
    {
        "$sort": {
            "name": -1
        }
    },
    {
        "$project": {
            "name": 1,
            "userActivities": {
                "$filter": {
                    "input": "$userActivities",
                    "as": "userActivities",
                    "cond": {
                        "$eq": [
                            "$$userActivities.actionTaken",
                            "Sign in."
                        ]
                    }
                }
            }
        }
    },
    {
        "$skip": 2
    },
    {
        "$limit": 2
    }
]

Но не получает никаких данных, даже если они соответствуют критериям фильтра. Если я удалю поле progress из выборки данных, оно даст мне данные.

Нужно ли что-то делать по-другому, когда в столбце для запроса есть несколько полей?

Использование JavaScript и MongoDB
Использование JavaScript и MongoDB
Сегодня я собираюсь вкратце рассказать о прототипах в JavaScript, а также представить и объяснить вам работу с базой данных MongoDB.
0
0
39
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Используйте точечную запись на этапе $match.

{
  "$match": {
    "userActivities.actionTaken": "Sign in."
  }
}

Образец игровой площадки Mongo

пытался. не работал.

Anonymous Creator 01.04.2022 13:27

Этот документы может быть вам полезен.

Yong Shun 01.04.2022 13:35

Может я что-то не так делал в прошлый раз. Но теперь это работает.

Anonymous Creator 01.04.2022 13:59

Возможно, добавьте «прогресс» на этапе сопоставления, иначе вы сопоставляете только объекты с одним полем actionTaken, которых нет в коллекции:

 {
  "$match": {
    "userActivities": {
      "actionTaken": "Sign in.",
      "progress": "Success."
    }
  }
 }

Образец игровой площадки Mongo

это неосуществимо. добавить прогресс также в фильтр, так как это не фактический фильтр.

Anonymous Creator 01.04.2022 13:27

действительно, вам лучше выполнить поиск с помощью точечной нотации «userActivities.actionTaken», как это было предложено @Yong Shun, и создать индекс для этого поля ...

R2D2 01.04.2022 13:29

Я получил ответ. Выложили сейчас.

Anonymous Creator 01.04.2022 13:29

поиск по точечной записи с индексом будет быстрее...

R2D2 01.04.2022 13:30

elemMatch лучше использовать, когда у вас есть более одного поля для поиска в подобъекте...

R2D2 01.04.2022 13:31

но запись через точку не работает. Я пробовал это.

Anonymous Creator 01.04.2022 13:35

в порядке. создать индекс для этого поля. Я пропустил эту часть. elemMatch на данный момент в порядке, так как у меня нет таких больших данных в таблице. Может быть, я рассмотрю для других таблиц, возможно. Но другие таблицы не имеют вложенных данных.

Anonymous Creator 01.04.2022 13:36

Давайте продолжить обсуждение в чате.

R2D2 01.04.2022 13:37

Получил ответ, приняв помощь от одного человека. Мне пришлось использовать $elemMatch следующим образом.

    [
      {
        "$match": {
          "userActivities": {
            "$elemMatch": {
              "actionTaken": "Sign in."
            }
          }
        }
      },
      {
        "$sort": {
          "name": -1
        }
      },
      {
        "$project": {
          "name": 1,
          "userActivities": {
            "$filter": {
              "input": "$userActivities",
              "as": "userActivities",
              "cond": {
                "$eq": ["$$userActivities.actionTaken", "Sign in."]
              }
            }
          }
        }
      },
      {
        "$skip": 2
      },
      {
        "$limit": 2
      }
    ]

Другие вопросы по теме