MongoDB汇总 - 仅在第二个集合上进行匹配条件,但提供了第一个文档

发布于 2025-02-09 19:54:50 字数 2453 浏览 1 评论 0原文

基本上,我的 mongodb 数据库中有2个集合 - >书籍,得分。

书籍

{
    "BOOK_ID" : "100",
    "BOOK_NAME" : "Book 1",
    "BOOK_DESC" : "abcd",
},
{
    "BOOK_ID" : "101",
    "BOOK_NAME" : "Book 2",
    "BOOK_DESC" : "efgh",
},
{
    "BOOK_ID" : "102",
    "BOOK_NAME" : "Book 3",
    "BOOK_DESC" : "ijkl",
}

分数

{
    "BOOK_ID" : "100",
    "BOOK_CATEGORY" : "kids",
    "BOOK_SCORE" : "6",
},
{
    "BOOK_ID" : "100",
    "BOOK_CATEGORY" : "Educational",
    "BOOK_SCORE" : "8",
},
{
    "BOOK_ID" : "101",
    "BOOK_CATEGORY" : "Kids",
    "BOOK_SCORE" : "6",
},
{
    "BOOK_ID" : "101",
    "BOOK_CATEGORY" : "Fantasy",
    "BOOK_SCORE" : "7",
}

预期输出: 使用books_category =“ kids”和`books_score = 6`请注意

{
    "BOOK_ID" : "100",
    "BOOK_NAME" : "Book 1",
    "BOOK_DESC" : "abcd",
    "BOOK_CATEGORY" : "Kids",
    "BOOK_SCORE" : 6
},
{
    "BOOK_ID" : "101",
    "BOOK_NAME" : "Book 2",
    "BOOK_DESC" : "efgh",
    "BOOK_CATEGORY" : "Kids",
    "BOOK_SCORE" : 6
},
{
    "BOOK_ID" : "102",
    "BOOK_NAME" : "Book 3",
    "BOOK_DESC" : "ijkl",
}

,请注意,对于所有可用分数的书籍,它们都会附加。如果一本书与任何分数没有任何相关性,那么结果仍然存在。

我尝试过的内容?

我尝试使用$ lookup

pipeline = [
                {
                    "$lookup": {
                    "from": "Scores",
                    "pipeline":[
                        {
                            "$match" : {
                                "BOOK_CATEGORY" : "Kids",
                                "BOOK_SCORE" : "6",
                            }
                        }
                    ],
                    "localField": "BOOK_ID",
                    "foreignField": "BOOK_ID",
                    "as": "SCORES", 

                    },
                },
            ]
db.Books.aggregate(pipeline)

,还通过阅读$ lookup subquery docs,( https> https:https:// www。 mongodb.com/docs/manual/reference/operator/aggregation/lookup/#join-conditions-and-subqueries-on-a-joined-collection ) 我感觉到我期望的可能是不可能的。 谁能帮助我执行此类查询? (我使用pymongo btw)

Basically, I have 2 collections in my MongoDB database -> Books, Scores.

Books

{
    "BOOK_ID" : "100",
    "BOOK_NAME" : "Book 1",
    "BOOK_DESC" : "abcd",
},
{
    "BOOK_ID" : "101",
    "BOOK_NAME" : "Book 2",
    "BOOK_DESC" : "efgh",
},
{
    "BOOK_ID" : "102",
    "BOOK_NAME" : "Book 3",
    "BOOK_DESC" : "ijkl",
}

Scores

{
    "BOOK_ID" : "100",
    "BOOK_CATEGORY" : "kids",
    "BOOK_SCORE" : "6",
},
{
    "BOOK_ID" : "100",
    "BOOK_CATEGORY" : "Educational",
    "BOOK_SCORE" : "8",
},
{
    "BOOK_ID" : "101",
    "BOOK_CATEGORY" : "Kids",
    "BOOK_SCORE" : "6",
},
{
    "BOOK_ID" : "101",
    "BOOK_CATEGORY" : "Fantasy",
    "BOOK_SCORE" : "7",
}

Expected output :
Searching for all books with BOOKS_CATEGORY="Kids" and `BOOKS_SCORE=6``

{
    "BOOK_ID" : "100",
    "BOOK_NAME" : "Book 1",
    "BOOK_DESC" : "abcd",
    "BOOK_CATEGORY" : "Kids",
    "BOOK_SCORE" : 6
},
{
    "BOOK_ID" : "101",
    "BOOK_NAME" : "Book 2",
    "BOOK_DESC" : "efgh",
    "BOOK_CATEGORY" : "Kids",
    "BOOK_SCORE" : 6
},
{
    "BOOK_ID" : "102",
    "BOOK_NAME" : "Book 3",
    "BOOK_DESC" : "ijkl",
}

Notice that, for all the books to which scores are available, they are appended. If a Book does not have any score associated, it still comes in the result.

What I have tried?

I have tried using $lookup

pipeline = [
                {
                    "$lookup": {
                    "from": "Scores",
                    "pipeline":[
                        {
                            "$match" : {
                                "BOOK_CATEGORY" : "Kids",
                                "BOOK_SCORE" : "6",
                            }
                        }
                    ],
                    "localField": "BOOK_ID",
                    "foreignField": "BOOK_ID",
                    "as": "SCORES", 

                    },
                },
            ]
db.Books.aggregate(pipeline)

Also, by reading the $lookup subquery docs,(https://www.mongodb.com/docs/manual/reference/operator/aggregation/lookup/#join-conditions-and-subqueries-on-a-joined-collection)
I got the feeling that what I am expecting may not be possible.
Can anyone help me with executing such query? (I use PyMongo btw)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

故事与诗 2025-02-16 19:54:50

对于最后两个阶段:

  1. $替换 - 通过将当前文档与该文档合并为分数数组。

  2. $ unset - 删除得分 array。

db.Books.aggregate([
  {
    "$lookup": {
      "from": "Scores",
      "pipeline": [
        {
          "$match": {
            "BOOK_CATEGORY": "Kids",
            "BOOK_SCORE": "6",
            
          }
        }
      ],
      "localField": "BOOK_ID",
      "foreignField": "BOOK_ID",
      "as": "SCORES"
    }
  },
  {
    "$replaceRoot": {
      "newRoot": {
        "$mergeObjects": [
          "$ROOT",
          {
            $first: "$ROOT.SCORES"
          }
        ]
      }
    }
  },
  {
    $unset: "SCORES"
  }
])

示例mongo playground

For the last two stages:

  1. $replaceRoot - Replace the input document(s) with the new document(s) by merging the current document with the document which is the first document from the SCORES array.

  2. $unset - Remove SCORES array.

db.Books.aggregate([
  {
    "$lookup": {
      "from": "Scores",
      "pipeline": [
        {
          "$match": {
            "BOOK_CATEGORY": "Kids",
            "BOOK_SCORE": "6",
            
          }
        }
      ],
      "localField": "BOOK_ID",
      "foreignField": "BOOK_ID",
      "as": "SCORES"
    }
  },
  {
    "$replaceRoot": {
      "newRoot": {
        "$mergeObjects": [
          "$ROOT",
          {
            $first: "$ROOT.SCORES"
          }
        ]
      }
    }
  },
  {
    $unset: "SCORES"
  }
])

Sample Mongo Playground

苍风燃霜 2025-02-16 19:54:50

您可以使用条件$ addfields,如果存在$ lookup值,则可以填充值,否则使用$$ remove像这样的领域:

db.Books.aggregate([
  {
    "$lookup": {
      "from": "Scores",
      "pipeline": [
        {
          "$match": {
            "BOOK_CATEGORY": "kids",
            "BOOK_SCORE": "6"
          }
        }
      ],
      "localField": "BOOK_ID",
      "foreignField": "BOOK_ID",
      "as": "SCORES"
    }
  },
  {
    $addFields: {
      SCORES: "$REMOVE",
      "BOOK_SCORE": {
        $cond: [
          {
            "$ifNull": [
              {
                "$arrayElemAt": [
                  "$SCORES",
                  0
                ]
              },
              false
            ]
          },
          {
            $getField: {
              field: "BOOK_SCORE",
              input: {
                "$arrayElemAt": [
                  "$SCORES",
                  0
                ]
              }
            }
          },
          "$REMOVE"
        ]
      },
      "BOOK_CATEGORY": {
        $cond: [
          {
            "$ifNull": [
              {
                "$arrayElemAt": [
                  "$SCORES",
                  0
                ]
              },
              false
            ]
          },
          {
            $getField: {
              field: "BOOK_CATEGORY",
              input: {
                "$arrayElemAt": [
                  "$SCORES",
                  0
                ]
              }
            }
          },
          "$REMOVE"
        ]
      },
      
    }
  }
])

mongo playground

You can achieve this by using a conditional $addFields, if the $lookup value exists then populate the values, else use $$REMOVE to remove the field, like so:

db.Books.aggregate([
  {
    "$lookup": {
      "from": "Scores",
      "pipeline": [
        {
          "$match": {
            "BOOK_CATEGORY": "kids",
            "BOOK_SCORE": "6"
          }
        }
      ],
      "localField": "BOOK_ID",
      "foreignField": "BOOK_ID",
      "as": "SCORES"
    }
  },
  {
    $addFields: {
      SCORES: "$REMOVE",
      "BOOK_SCORE": {
        $cond: [
          {
            "$ifNull": [
              {
                "$arrayElemAt": [
                  "$SCORES",
                  0
                ]
              },
              false
            ]
          },
          {
            $getField: {
              field: "BOOK_SCORE",
              input: {
                "$arrayElemAt": [
                  "$SCORES",
                  0
                ]
              }
            }
          },
          "$REMOVE"
        ]
      },
      "BOOK_CATEGORY": {
        $cond: [
          {
            "$ifNull": [
              {
                "$arrayElemAt": [
                  "$SCORES",
                  0
                ]
              },
              false
            ]
          },
          {
            $getField: {
              field: "BOOK_CATEGORY",
              input: {
                "$arrayElemAt": [
                  "$SCORES",
                  0
                ]
              }
            }
          },
          "$REMOVE"
        ]
      },
      
    }
  }
])

Mongo Playground

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文