需求
已知下级字段的名称,想要查询所有匹配该级字段名称和值的mongodb数据
技术难点
需要通配不知名称和级别的上级字段
sql示例
db.formData.find({"data.?.quote_source_id": NumberLong("1197023880636665856")})
或
db.formData.find({"data.?.value.value.?.quote_source_id": NumberLong("1197023880636665856")})
研究结果
mongo DB 没有这种通配符;
解决方案
规避采用这种使用通配符的方案,采用另外一种办法,将所有可能通配的值都列出来,遍历查询所有的情况。
具体代码如下:
/**
* 获取引用的数据
*
* @param formQuoteField formId和字段名的映射
* @param sourceFormDataId 来源表ID
* @param tenantId 企业ID
* @return 引用的数据
*/
@Override
public List<FormData> getQuoteList(Map<Long, List<String>> formQuoteField, Long sourceFormDataId, Long tenantId) {
List<Criteria> criteriaOut = new ArrayList<>();
for (Map.Entry<Long, List<String>> entry : formQuoteField.entrySet()) {
if (CollectionUtils.isEmpty(entry.getValue())) {
continue;
}
List<Criteria> criteriaIn = new ArrayList<>();
for (String filedName : entry.getValue()) {
if (StringUtils.isEmpty(filedName)) {
continue;
}
Criteria criteriaField = new Criteria();
if (!filedName.contains(".")) {
criteriaField.and("data." + filedName + ".quote_source_id").is(sourceFormDataId);
}
if (filedName.contains(".")) {
String[] split = filedName.split("\\.");
criteriaField.and("data." + split[0] + ".value.value." + split[1] + ".quote_source_id").is(sourceFormDataId);
}
criteriaIn.add(criteriaField);
}
Criteria criteria = new Criteria();
criteria.and("form_id").is(entry.getKey()).and("tenant_id").is(tenantId);
if (criteriaIn.size() > 1) {
criteria.orOperator(criteriaIn.toArray(new Criteria[criteriaIn.size()]));
} else if (criteriaIn.size() == 1) {
criteria.orOperator(criteriaIn.get(0));
}
criteriaOut.add(criteria);
}
Criteria finao = new Criteria();
if (!CollectionUtils.isEmpty(criteriaOut)) {
finao.orOperator(criteriaOut.toArray(new Criteria[criteriaOut.size()]));
}
Query query = new Query();
query.addCriteria(finao);
return mongoTemplate.find(query, FormData.class, "formData");
}