Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb Spring Data Mongo-在嵌入式文档中应用唯一的组合字段_Mongodb_Spring Data Mongodb - Fatal编程技术网

Mongodb Spring Data Mongo-在嵌入式文档中应用唯一的组合字段

Mongodb Spring Data Mongo-在嵌入式文档中应用唯一的组合字段,mongodb,spring-data-mongodb,Mongodb,Spring Data Mongodb,我正在开发springbootv2.1.3.RELEASE和springdatamongo。在本例中,我希望在电子邮件和deptName上应用唯一性。电子邮件和deptName的组合必须是唯一的,并且由于电子邮件在每个数组对象中重复,是否有任何方法可以将其取出 我在下面试过了,但没用 @CompoundIndexes({ @CompoundIndex(name = "email_deptName_idx", def = "{'email' : 1, 'technologyEmployee

我正在开发
springbootv2.1.3.RELEASE和springdatamongo
。在本例中,我希望在电子邮件和deptName上应用唯一性。电子邮件和deptName的组合必须是唯一的,并且由于电子邮件在每个数组对象中重复,是否有任何方法可以将其取出

我在下面试过了,但没用

@CompoundIndexes({
    @CompoundIndex(name = "email_deptName_idx", def = "{'email' : 1, 'technologyEmployeeRef.technologyCd' : 1}")
})
样本数据

{
    "_id" : ObjectId("5ec507c72d8c2136245d35ce"),
    ....
    ....
    "firstName" : "John",
    "lastName" : "Doe",
    "email" : "john.doe@gmail.com",
    .....
    .....
    .....
    "technologyEmployeeRef" : [ 
        {
            "technologyCd" : "john.doe@gmail.com",
            "technologyName" : "Advisory",
            ....
            .....
            "Status" : "A"
        }, 
        {
           "technologyCd" : "john.doe@gmail.com",
           "technologyName" : "Tax",
           .....
           .....
           "Status" : "A"
       }
    ],
    "phoneCodes" : [ 
        "+352"
    ],
    ....
    ....
}
Technology.java

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Document
public class Technology {
    @Indexed(name = "technologyCd", unique = true, sparse = true)
    private String technologyCd;

    @Indexed(name = "technologyName", unique = true, sparse = true)
    private String technologyName;
    private String status;
}
EmployeeTechnologyRef.java

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class EmployeeTechnologyRef {
    private String technologyCd;
    private String primaryTechnology;
    private String status;
}
Employee.java

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Document
@CompoundIndexes({
    @CompoundIndex(name="emp_tech_indx", def = "{'employeeTechnologyRefs.primaryTechnology' : 1, 'employeeTechnologyRefs.technologyCd' : 1}" ,unique = true, sparse = true)
})
public class Employee {
    private String firstName;
    private String lastName;
    private String email;
    private List<EmployeeTechnologyRef> employeeTechnologyRefs;
}
@数据
@建筑商
@AllArgsConstructor
@诺尔格构装师
@文件
@复合指数({
@CompoundIndex(name=“emp_tech_indx”,def=“{'employeeTechnologyRefs.primaryTechnology':1,'employeeTechnologyRefs.technologyCd':1}”,unique=true,sparse=true)
})
公营雇员{
私有字符串名;
私有字符串lastName;
私人字符串电子邮件;
私人名单员工技术参考;
}
我用了下面的代码,但它没有给我任何重复的错误。我们怎样才能做到这一点

Technology java8 = Technology.builder().technologyCd("Java").technologyName("Java8").status("A").build();
Technology spring = Technology.builder().technologyCd("Spring").technologyName("Spring Boot2").status("A").build();
List<Technology> technologies = new ArrayList<>();
technologies.add(java8);
technologies.add(spring);

technologyRepository.saveAll(technologies);

EmployeeTechnologyRef t1 = EmployeeTechnologyRef.builder().technologyCd("Java").primaryTechnology("Y")
        .status("A")
        .build();
EmployeeTechnologyRef t2 = EmployeeTechnologyRef.builder().technologyCd("Spring").primaryTechnology("Y")
        .status("A")
        .build();
List<EmployeeTechnologyRef> employeeTechnologyRefs = new ArrayList<>();
employeeTechnologyRefs.add(t1);
employeeTechnologyRefs.add(t2);
employeeTechnologyRefs.add(t1);

Employee employee = Employee.builder().firstName("John").lastName("Kerr").email("john.kerr@gmail.com")
        .employeeTechnologyRefs(employeeTechnologyRefs).build();
employeeRepository.save(employee);
technologyJava8=Technology.builder().technologyCd(“Java”).technologyName(“java8”).status(“A”).build();
Technology spring=Technology.builder().technologyCd(“spring”).technologyName(“spring Boot2”).status(“A”).build();
List technologies=new ArrayList();
add(java8);
添加(spring);
技术报告。保存所有(技术);
EmployeeTechnologyRef t1=EmployeeTechnologyRef.builder().technologyCd(“Java”).primaryTechnology(“Y”)
.地位(“A”)
.build();
EmployeeTechnologyRef t2=EmployeeTechnologyRef.builder().technologyCd(“Spring”).primaryTechnology(“Y”)
.地位(“A”)
.build();
List employeeTechnologyRefs=new ArrayList();
员工技术参考添加(t1);
员工技术参考添加(t2);
员工技术参考添加(t1);
Employee Employee=Employee.builder().firstName(“约翰”).lastName(“克尔”).email(“约翰。kerr@gmail.com")
.employeeTechnologyRefs(employeeTechnologyRefs).build();
employeeRepository.save(雇员);

在MongoDB中,唯一索引确保字段中的特定值不会出现在多个文档中。它将保证单个文档中的数组中的值是唯一的。MongoDB手册对此进行了解释,其中讨论了唯一的多键索引

因此,唯一索引将无法满足您的要求。它将防止单独的文档包含重复的组合,但仍允许单个文档包含跨数组的重复值

您最好的选择是更改数据模型,以便将technologyEmployeeRef对象数组拆分为单独的文档。将其拆分为单独的文档将允许您使用唯一索引来强制执行唯一性

此数据模型更改应采取的具体实现取决于您的访问模式(这超出了本问题的范围)


其中一种方法是创建一个TechnologyEmployeer集合,该集合包含technologyEmployeeRef数组中当前存在的所有字段。此外,此技术Employee集合将有一个字段,例如电子邮件,允许您将其与Employee集合中的文档关联

员工文件样本

{
  ....
  ....
  "firstName" : "John",
  "lastName" : "Doe",
  "email" : "john.doe@gmail.com",
  .....
  .....
  .....
}
雇员技术文件样本

{
  "email" : "john.doe@gmail.com",
  "technologyCd" : "Java",
  "technologyName" : "Java8",
  ....
  .....
  "status" : "A"
}
员工技术集合中的索引

{'email' : 1, 'technologyCd' : 1}, {unique: true}
这种方法的缺点是需要从两个集合中读取所有数据。如果您很少需要同时从两个集合检索数据,那么这个缺点可能不是什么大问题。如果您确实需要所有数据,可以通过使用索引来加快速度。有了这些指标,就可以通过使用


另一种选择是对数据进行非规范化。您可以通过复制需要与技术数据同时访问的员工数据来实现这一点

样本文件

[
  {
    ....
    "firstName" : "John",
    "lastName" : "Doe",
    "email" : "john.doe@gmail.com",
    .....
    "technologyCd" : "Java",
    "technologyName" : "Java8",
    ....
    "status" : "A"
  },
  {
    ....
    "firstName" : "John",
    "lastName" : "Doe",
    "email" : "john.doe@gmail.com",
    .....
    "technologyCd" : "Spring",
    "technologyName" : "Spring Boot2",
    ....
    "status" : "A"
  }
]
事实上,他们说

您只会对经常读取的字段执行此操作,这些字段的读取频率比更新频率高很多,并且不需要强一致性,因为更新非规范化值的速度较慢、成本更高,而且不是原子的


或者正如您已经提到的,保持数据模型不变并在应用程序端执行唯一性检查可能是有意义的。这可能会给您带来最好的阅读性能,但它确实有一些缺点。首先,它会减慢写操作,因为应用程序需要运行一些检查才能更新数据库

这可能不太可能,但也有一种可能,你仍然可以最终与重复。如果有两个背对背的请求将同一EmployeeTechnology对象插入数组,则第二个请求的验证可能会在第一个请求写入数据库之前完成(并通过)。我在自己开发的应用程序中也看到过类似的场景。即使应用程序正在检查唯一性,如果用户双击submit按钮,数据库中也会出现重复条目。在这种情况下,在第一次单击时禁用按钮可显著降低风险。这一小风险可能是可以容忍的,这取决于您的要求和重复条目的影响



哪种方法最有意义很大程度上取决于您的访问模式和需求。希望这能有所帮助。

关于嵌入文档中字段的唯一索引,有一些有用的信息:我已经看过了,许多其他类似的链接并不能解决我的问题problems@prasad_-请在此提供关于此问题的明确答案?因为这不能解决我的问题,所以你的问题需要一些编辑。不清楚你在问什么。1) 第一部分与第二部分不匹配。首先,您询问的是电子邮件和部门名称,然后