本文介绍了我如何实现此mongodb查询&更新操作(CSharp驱动程序)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个收藏集:

Books
[
{
  title: Book1,
  References: [ObjectId(1), ObjectId(3), ObjectId(5)] <- These are object ids of another collection
  Main-Reference: ObjectId(5)
},
{
  title: Book2,
  References: [ObjectId(2), ObjectId(5), ObjectId(7)] 
  Main-Reference: ObjectId(5)
}
{
  title: Book3,
  References: [ObjectId(5), ObjectId(7), ObjectId(9)] 
  Main-Reference: ObjectId(7)
},
]

我有一项操作,该操作是从藏书中删除参考书目示例:假设我必须从集合中删除Reference ObjectId(5)所以我的新收藏变成了:

I have an operation where I delete a Reference from book collectionExample: Assume I have to delete Reference ObjectId(5) from my collectionSo my new collection become this:

Books
[
{
  title: Book1,
  References: [ObjectId(1), ObjectId(3)] <- ObjectId(5) is pulled
  Main-Reference: ObjectId(1) <- ObjectId(1) is new value as ObjectId(5) is deleted
},
{
  title: Book2,
  References: [ObjectId(2), ObjectId(7)]  <- ObjectId(5) is pulled
  Main-Reference: ObjectId(2) <- ObjectId(2) is now main reference
}
{
  title: Book3,
  References: [ObjectId(7), ObjectId(9)] <- ObjectId(5) is pulled
  Main-Reference: ObjectId(7) <- no changes here as ObjectId(7) still exists in References
},
]

目前这是我的工作方式

第1步:从References []具有ObjectId(5)的所有书籍中提取ObjectId(5)

Step 1: Pull ObjectId(5) from all Books where References[] has ObjectId(5)

第2步:查询图书参考"集合,其中Main-Reference = ObjectId(5)&使用引用:{$ slice:1} slice从引用​​数组中获取第一个数组元素

Step 2: Query Books collection where Main-Reference=ObjectId(5) & use References: {$slice:1} slice to get the first array element from References array

第3步:更新第2步和第2步中找到的所有书籍.用从切片中获得的第一个数组元素替换Main-Reference

Step 3: Update all of the books found in Step 2 & replace Main-Reference with the first array element I get from slice

这对我来说似乎很笨拙,试图查看是否有更好的方法可以做到这一点.

This seems clumsy to me and trying to see if there is a better way to do this.

推荐答案

如果我基本上明白了你的要旨,

If I essentially get your gist you basically want to

  1. 从您的引用数组中拉出不需要的项目
  2. 将主引用字段的值设置为更改后的数组的第一个元素

一次完成所有更新,而无需在网络上移动文档.

And get that done all in one update without moving documents across the wire.

但是可悲的是无法做到这一点.这样做的主要问题是无法引用正在更新的文档中另一个字段的值.即使这样,要不进行迭代也要访问 changed 数组以获得新的第一个元素.

But this sadly cannot be done. The main problem with this is that there is no way to refer to the value of another field within the document being updated. Even so, to do this without iterating you would also need to access the changed array in order to get the new first element.

也许一种方法是重新考虑您的架构以完成所需的工作.在这里,我的选择是稍微扩展您的参考文档,并消除对主要参考字段的需求.

Perhaps one approach is to re-think your schema in order to accomplish what you want. My option here would expanding on your references documents a little and removing the need for the main-reference field.

似乎愿意在更新中使用的假设是,如果删除的引用是主引用,则可以将新的主引用设置为数组中的第一个元素.考虑到这一点,请考虑以下结构:

It seems that the assumption you are willing to live with on the updates is that if the removed reference was the main-reference then you can just set the new main-reference to the first element in the array. With that in mind consider the following structure:

refs: [ { oid: "object1" }, { oid: "object2" }, { oid: "object5", main: true } ]

通过将其更改为具有将设置为ObjectId的oid属性的文档,它提供了在文档上具有指定默认属性的附加属性的选项.可以很容易地查询到哪个ID是主要参考.

By changing these to documents with an oid property that would be set to the ObjectId it gives the option to have an additional property on the document that specifies which is the default. This can easily be queried determine which Id is the main reference.

现在还考虑如果从数组中提取与oid字段中匹配"object5"的文档会发生什么情况?

Now also consider what would happen if the document matching "object5" in the oid field was pulled from the array:

refs: [ { oid: "object1" }, { oid: "object2" } ]

因此,当您根据较早的逻辑查询哪个是main-reference时,您会接受数组中的第一个文档.现在,当然,根据您的应用程序要求,如果要设置其他main-reference,则只需更改文档

So when you query for which is the main-reference as per the earlier logic you accept the first document in the array. Now of course, to your application requirements, if you want to set a different main-reference you just alter the document

refs: [ { oid: "object1" }, { oid: "object2", main: true } ]

现在逻辑仍然是优先选择具有主要属性的数组元素,如上所示,如果该属性在任何元素文档中都不存在,则退回到第一个元素.

And now the logic remains to choose the array element that has the main property as true would occur in preference, and as shown above that if that property does not exist on any elements document then fall back to the first element.

所有这些都消化完之后,将所有对象的所有引用从所有文档中的数组中拉出的操作变得非常简单,就像在shell中一样(相同的格式基本上适用于任何驱动程序):

With all of that digested, your operation to pull all references to an object out of that array in all documents becomes quite simple, as done in the shell ( same format should basically apply to whatever driver ):

db.books.update(
   { "refs.oid": "object5" },
   { $pull: { refs: {oid: "object5"} } }, false, true )

查询和更新操作的两个额外参数分别为upsertmulti.在这种情况下,upsert没有多大意义,因为我们只想修改存在的文档,而multi意味着我们要更新所有匹配的文档.默认设置是仅更改第一个文档.

The two extra arguments to the query and update operation being upsert and multi respectively. In this case, upsert does not make much sense as we only want to modify documents that exist, and multi means that we want to update everything that matched. The default is to change just the first document.

自然,我缩短了所有符号,但是根据您的意图,这些值当然可以是实际的ObjectId.假定main-reference的主要用法是在检索文档之后,这似乎也很合理.通过遵循概述的逻辑来定义一个返回main-reference的查询应该是可能的,但是就目前而言,我在这里输入了很多内容,需要休息一下:)

Naturally I shortened all the notation but of course the values can be actual ObjectId's as per your intent. It seemed also reasonable to presume that your main usage of the main-reference is once you have retrieved the document. Defining a query that returns the main-reference by following the logic that was outlined should be possible, but as it stands I have typed a lot out here and need to break for dinner :)

我认为这为重新考虑您的模式提供了一个值得考虑的案例,从而避免了您想要实现的遍历迭代.

I think this presents a worthwhile case for re-thinking your schema to avoid over the wire iterations for what you want to achieve.

这篇关于我如何实现此mongodb查询&amp;更新操作(CSharp驱动程序)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 21:59