在mongoDB中,函数AddToSet添加重复项

时间:2018-07-08 07:37:57

标签: mongodb mongodb-.net-driver

我正在使用MongoDB $addToSet,如下所示:

.AddToSet(report => report.EngineReports, engineReport);

EngineReport是类,而不是MongoDB文档中的字符串或整数,它是类FileAggregationReport中的一部分:

public class FileAggregateReport
{        
    public Guid FileId { get; set; }

    public Guid CorrelationId { get; set; }

    public List<EngineReport> EngineReports { get; set; }      

}

现在我的问题是我有重复项,因为如果我有2个具有相同ID但其他属性不同的对象,则会将这2个类添加到集合中。

示例:

头等舱

new EngineReport()
    {
         EngineType = EngineType.TypeA,
         Summary = "test1"
    }

第二堂课

new EngineReport()
    {
         EngineType = EngineType.TypeA,
         Summary = "test2"
    }

因此,当我使用addToSet将其添加到EngineReports时,我的问题是2个类,但我只想添加一个,是否可以?

如何在addToset之前检查此类是否与集合中的ID相同?

1 个答案:

答案 0 :(得分:1)

来自$addToSet文档:

  

如果值为文档,则如果数组中的现有文档与要添加的文档完全完全匹配,则MongoDB会确定该文档为重复文档;即现有文档具有完全相同的相同字段,且这些字段的顺序相同

因此,这对您的情况没有帮助。

您可以采用其他方法,并在更新操作中更改过滤器部分。例如,假设当前您通过FileId字段进行匹配。您可以添加其他检查,以确保更新的文档中没有EngineType.TypeA。这将对您尝试插入的第一个EngineReport有效,但对于第二个var filterBuilder = Builders<FileAggregateReport>.Filter; var regularFilter = filterBuilder.Eq(x => x.FileId, fileId); var engineType = Builders<EngineReport>.Filter.Eq(x => x.EngineType, EngineType.TypeA); var engineTypeFilter = filterBuilder.ElemMatch(f => f.EngineReports, engineType); var combinedFilter = filterBuilder.And(regularFilter, filterBuilder.Not(engineTypeFilter)); var updateBuilder = Builders<FileAggregateReport>.Update; var update1 = updateBuilder.Push(x => x.EngineReports, engineReport1); var update2 = updateBuilder.Push(x => x.EngineReports, engineReport2); myCollection.UpdateOne(combinedFilter, update1); // 1 document affected myCollection.UpdateOne(combinedFilter, update2); // 0 documents affected ,则不会更新任何文档:

/// Updates The Contents Of Each Node Added To Our NodesAdded Array
///
/// - Parameters:
///   - nodes: [SCNNode]
///   - pointOfView: SCNNode
func updateScaleFromCameraForNodes(_ nodes: [SCNNode], fromPointOfView pointOfView: SCNNode){

    nodes.forEach { (node) in

        //1. Get The Current Position Of The Node
        let positionOfNode = SCNVector3ToGLKVector3(node.worldPosition)

        //2. Get The Current Position Of The Camera
        let positionOfCamera = SCNVector3ToGLKVector3(pointOfView.worldPosition)

        //3. Calculate The Distance From The Node To The Camera
        let distanceBetweenNodeAndCamera = GLKVector3Distance(positionOfNode, positionOfCamera)

        //4. Animate Their Scaling & Set Their Scale Based On Their Distance From The Camera
        SCNTransaction.begin()
        SCNTransaction.animationDuration = 0.5
        switch distanceBetweenNodeAndCamera {
        case 0 ... 0.5:
            node.simdScale = simd_float3(0.25, 0.25, 0.25)
        case 0.5 ... 1:
            node.simdScale = simd_float3(0.5, 0.5, 0.5)
        case 1 ... 1.5:
            node.simdScale = simd_float3(1, 1, 1)
        case 1.5 ... 2:
            node.simdScale = simd_float3(1.5, 1.5, 1.5)
        case 2 ... 2.5:
            node.simdScale = simd_float3(2, 2, 2)
        case 2.5 ... 3:
            node.simdScale = simd_float3(2.5, 2.5, 2.5)
        default:
            print("Default")
        }
        SCNTransaction.commit()
    }

}