MongoDB:如何通过嵌套文档中的id查找文档

时间:2015-05-05 05:17:55

标签: mongodb mongodb-query embedded-documents

给出这样的集合:..

[
  {
    "_id" : ObjectId("5546329a470000850084a621"),
    "name": "Joe",
    "surname": "Smith",
    "accounts": [
      {
        "_id" : ObjectId("5546329a470000850084a655"),
        "default": true,
        "status" : "approved",
        "activationTime" : ISODate("2013-05-03T14:37:15.025Z")
      },
      {
        "_id" : ObjectId("5546329a470000850084a688"),
        "default": true,
        "status" : "approved",
        "activationTime" : ISODate("2014-06-03T14:37:15.025Z")
      }
    ]
  },
  {
    "_id" : ObjectId("9546329a470079850084a622"),
    "name": "Jimmy",
    "surname": "Brown",
    "accounts": [
      {
        "_id" : ObjectId("5546329a470790850084a651"),
        "default": true,
        "status" : "suspended",
        "activationTime" : ISODate("2015-02-03T14:37:15.025Z")
      },
      {
        "_id" : ObjectId("5546329a470019850084a611"),
        "default": true,
        "status" : "approved",
        "activationTime" : ISODate("2015-04-03T14:37:15.025Z")
      }
    ]
  },
]

...如何找到accounts.N._id的文件?我试过这个......

db.users.find(
  {},
  {
    "accounts": 0, "accounts": {
      "$elemMatch": { "_id" : ObjectId("5546329a470019850084a611"), "default": true }
    }
  }
)

...但由于我只收到所有文件的_id,所以它不起作用:

{ "_id" : ObjectId("5546329a470000850084a621") }
{ "_id" : ObjectId("9546329a470079850084a622") }

我错过了什么吗?

修改

我实际需要的结果是这样的:

{
  "_id" : ObjectId("9546329a470079850084a622"),
  "name": "Jimmy",
  "surname": "Brown"
}

例如,我需要通过accounts.N._id查找,但不显示嵌套文档本身。

3 个答案:

答案 0 :(得分:19)

使用dot notation

  

当该字段包含嵌入的文档时,查询可以指定   嵌入文档的完全匹配或指定匹配   嵌入文档中的各个字段使用点表示法。

jQuery.sap.declare("app.Component");
//jQuery.sap.require("app.MyRouter");

sap.ui.core.UIComponent.extend("app.Component", {
    metadata: {
        name: "DEmo App",
        version: "1.0",
        includes: [],
        dependencies: {
            libs: ["sap.m", "sap.ui.layout"], //add any other libraries you need
            components: []
        },

        //rootView : "app.view.App",

        config: {
            resourceBundle: "i18n/i18n.properties",
            //if you have service
            /*serviceConfig : {
                name: "SERVICE_NAME",
                serviceUrl: "/your/service/url/"
            }*/
        },

        routing: {

            routes: [
              //your routes
      ]
        }
    },

    init: function () {
        sap.ui.core.UIComponent.prototype.init.apply(this, arguments);

        var mConfig = this.getMetadata().getConfig();

        // Always use absolute paths relative to our own component
        // (relative paths will fail if running in the Fiori Launchpad)
        var oRootPath = jQuery.sap.getModulePath("app");

        // Set i18n model
        var i18nModel = new sap.ui.model.resource.ResourceModel({
            bundleUrl: [oRootPath, mConfig.resourceBundle].join("/")
        });
        this.setModel(i18nModel, "i18n");

        var sServiceUrl = mConfig.serviceConfig.serviceUrl;

        //This code is only needed for testing the application when there is no local proxy available
        var bIsMocked = jQuery.sap.getUriParameters().get("responderOn") === "true";
        // Start the mock server for the domain model
        if (bIsMocked) {
            this._startMockServer(sServiceUrl);
        }

        // Create and set domain model to the component
        var oModel = new sap.ui.model.odata.ODataModel(sServiceUrl, {
            json: true,
            loadMetadataAsync: true
        });

        // if you have static models
        //  var oModel = new sap.ui.model.odata.ODataModel([oRootPath, "model/coffee.json"].join("/"), {json: true,loadMetadataAsync: true});
        this.setModel(oModel);

        // Set device model if needed
        var oDeviceModel = new sap.ui.model.json.JSONModel({
            isTouch: sap.ui.Device.support.touch,
            isNoTouch: !sap.ui.Device.support.touch,
            isPhone: sap.ui.Device.system.phone,
            isNoPhone: !sap.ui.Device.system.phone,
            listMode: sap.ui.Device.system.phone ? "None" : "SingleSelectMaster",
            listItemType: sap.ui.Device.system.phone ? "Active" : "Inactive"
        });
        oDeviceModel.setDefaultBindingMode("OneWay");
        this.setModel(oDeviceModel, "device");

        //this.getRouter().initialize();

    }
});

如果您只需输出数组中有_id的部分,则需要使用dollar in projection

  

位置$运算符限制了a的内容   查询结果只包含与查询匹配的第一个元素   文档。

,您的查询将如下所示:

db.coll.find({
   "accounts._id" :ObjectId("5546329a470019850084a611")
})

P.S。如果你需要像你修改过的问题那样输出,请使用:

db.coll.find({
   "accounts._id" :ObjectId("5546329a470019850084a611")
}, {
   "accounts.$.": 1
})

答案 1 :(得分:5)

$ elemMatch运算符将查询结果中字段的内容限制为仅包含与$ elemMatch条件匹配的第一个元素。

在你的情况下:

<string name="hello">Bonjour</string>

参考:Mongo Docs

答案 2 :(得分:1)

在条件中使用$elemMatch并在项目中使用$位置运算符,如下所示:

db.users.find({
  "accounts": {
    "$elemMatch": {
      "_id": ObjectId("5546329a470019850084a611"),
      "default": true
    }
  }
}, {
  "accounts.$._id": 1 // "accounts.$": 1 also works
}).pretty()