更新元数据后发现不适用于 GridFS
Find not working for GridFS after updating metadata
我在我的应用程序中添加了一个步骤以通过 GridFS 保存文件,并添加了一个名为 "processed" 的元数据字段作为计划任务的标志,该任务检索新文件并将其发送以进行处理。由于 GridFS 的 Java 驱动程序没有允许更新元数据的方法,因此我对 "fs.files" 集合使用 MongoCollection 来将 "metadata.processing" 更新为 true。
我使用 GridFSBucket.find(eq("metadata.processed", false) 来获取要处理的新文件,然后在处理完成后将 metadata.processed 更新为 true。如果我添加一个新文件,而应用程序是 运行。但是,如果我有一个 "metadata.processed" 设置为 false 的现有文件并启动应用程序,上面的查找调用 returns 没有结果。同样,如果我有一个已经处理过的文件,我将 "metadata.processed" 字段设置回 false,上面的查找调用也停止工作。
private static final String FILTER_STR = "'{'\"filename\" : \"{0}\"'}'";
private static final String UPDATE_STR =
"'{'\"$set\": '{'\"metadata.processed\": \"{0}\"'}}'";
@Autowired
private GridFSBucketFactory gridFSBucketFactory;
@Autowired
private MongoCollectionFactory mongoCollectionFactory;
public void storeFile(String filename, DateTime publishTime,
InputStream inputStream) {
if (fileExists(filename)) {
LOGGER.info("File named {} already exists.", filename);
} else {
uploadToGridFS(filename, publishTime, inputStream);
LOGGER.info("Stored file named {}.", filename);
}
}
public GridFSDownloadStream getFile(BsonValue id) {
return gridFSBucketFactory.getGridFSBucket().openDownloadStream(id);
}
public GridFSDownloadStream getFile(String filename) {
final GridFSFile file = getGridFSFile(filename);
return file == null ? null : getFile(file.getId());
}
public GridFSFindIterable getUnprocessedFiles() {
return gridFSBucketFactory.getGridFSBucket()
.find(eq("metadata.processed", false));
}
public void setProcessed(String filename, boolean isProcessed) {
final BasicDBObject filter =
BasicDBObject.parse(format(FILTER_STR, filename));
final BasicDBObject update =
BasicDBObject.parse(format(UPDATE_STR, isProcessed));
if (updateOne(filter, update)) {
LOGGER.info("Set metadata for {} to {}", filename, isProcessed);
}
}
private void uploadToGridFS(String filename, DateTime publishTime,
InputStream inputStream) {
gridFSBucketFactory.getGridFSBucket().uploadFromStream(filename,
inputStream, createMetadata(publishTime));
}
private GridFSUploadOptions createMetadata(DateTime publishTime) {
final Document metadata = new Document();
metadata.put("processed", false);
// metadata.put("publishTime", publishTime.toString());
return new GridFSUploadOptions().metadata(metadata);
}
private boolean fileExists(String filename) {
return getGridFSFile(filename) != null;
}
private GridFSFile getGridFSFile(String filename) {
return gridFSBucketFactory.getGridFSBucket()
.find(eq("filename", filename)).first();
}
private boolean updateOne(BasicDBObject filter, BasicDBObject update) {
try {
mongoCollectionFactory.getFsFilesCollection().updateOne(filter,
update, new UpdateOptions().upsert(true));
} catch (final MongoException e) {
LOGGER.error(
"The following failed to update, filter:{0} update:{1}",
filter, update, e);
return false;
}
return true;
}
知道我能做些什么来确保:
GridFSBucket.find(eq("metadata.processed", false)
returns 现有文件的正确结果 and/or 已更改元数据的文件?
问题是由于将 metadata.processed 值设置为字符串与布尔值。
最初创建元数据时,我用布尔值设置它的值:
private GridFSUploadOptions createMetadata(DateTime publishTime) {
final Document metadata = new Document();
metadata.put("processed", false);
// metadata.put("publishTime", publishTime.toString());
return new GridFSUploadOptions().metadata(metadata);
}
然后我检查一个布尔值:
public GridFSFindIterable getUnprocessedFiles() {
return gridFSBucketFactory.getGridFSBucket()
.find(eq("metadata.processed", false));
}
但是在使用 "fs.files" MongoCollection 更新元数据时,我错误地在此处的布尔值周围添加了引号:
private static final String UPDATE_STR =
"'{'\"$set\": '{'\"metadata.processed\": \"{0}\"'}}'";
这导致元数据值被保存为字符串而不是布尔值。
我在我的应用程序中添加了一个步骤以通过 GridFS 保存文件,并添加了一个名为 "processed" 的元数据字段作为计划任务的标志,该任务检索新文件并将其发送以进行处理。由于 GridFS 的 Java 驱动程序没有允许更新元数据的方法,因此我对 "fs.files" 集合使用 MongoCollection 来将 "metadata.processing" 更新为 true。
我使用 GridFSBucket.find(eq("metadata.processed", false) 来获取要处理的新文件,然后在处理完成后将 metadata.processed 更新为 true。如果我添加一个新文件,而应用程序是 运行。但是,如果我有一个 "metadata.processed" 设置为 false 的现有文件并启动应用程序,上面的查找调用 returns 没有结果。同样,如果我有一个已经处理过的文件,我将 "metadata.processed" 字段设置回 false,上面的查找调用也停止工作。
private static final String FILTER_STR = "'{'\"filename\" : \"{0}\"'}'";
private static final String UPDATE_STR =
"'{'\"$set\": '{'\"metadata.processed\": \"{0}\"'}}'";
@Autowired
private GridFSBucketFactory gridFSBucketFactory;
@Autowired
private MongoCollectionFactory mongoCollectionFactory;
public void storeFile(String filename, DateTime publishTime,
InputStream inputStream) {
if (fileExists(filename)) {
LOGGER.info("File named {} already exists.", filename);
} else {
uploadToGridFS(filename, publishTime, inputStream);
LOGGER.info("Stored file named {}.", filename);
}
}
public GridFSDownloadStream getFile(BsonValue id) {
return gridFSBucketFactory.getGridFSBucket().openDownloadStream(id);
}
public GridFSDownloadStream getFile(String filename) {
final GridFSFile file = getGridFSFile(filename);
return file == null ? null : getFile(file.getId());
}
public GridFSFindIterable getUnprocessedFiles() {
return gridFSBucketFactory.getGridFSBucket()
.find(eq("metadata.processed", false));
}
public void setProcessed(String filename, boolean isProcessed) {
final BasicDBObject filter =
BasicDBObject.parse(format(FILTER_STR, filename));
final BasicDBObject update =
BasicDBObject.parse(format(UPDATE_STR, isProcessed));
if (updateOne(filter, update)) {
LOGGER.info("Set metadata for {} to {}", filename, isProcessed);
}
}
private void uploadToGridFS(String filename, DateTime publishTime,
InputStream inputStream) {
gridFSBucketFactory.getGridFSBucket().uploadFromStream(filename,
inputStream, createMetadata(publishTime));
}
private GridFSUploadOptions createMetadata(DateTime publishTime) {
final Document metadata = new Document();
metadata.put("processed", false);
// metadata.put("publishTime", publishTime.toString());
return new GridFSUploadOptions().metadata(metadata);
}
private boolean fileExists(String filename) {
return getGridFSFile(filename) != null;
}
private GridFSFile getGridFSFile(String filename) {
return gridFSBucketFactory.getGridFSBucket()
.find(eq("filename", filename)).first();
}
private boolean updateOne(BasicDBObject filter, BasicDBObject update) {
try {
mongoCollectionFactory.getFsFilesCollection().updateOne(filter,
update, new UpdateOptions().upsert(true));
} catch (final MongoException e) {
LOGGER.error(
"The following failed to update, filter:{0} update:{1}",
filter, update, e);
return false;
}
return true;
}
知道我能做些什么来确保:
GridFSBucket.find(eq("metadata.processed", false)
returns 现有文件的正确结果 and/or 已更改元数据的文件?
问题是由于将 metadata.processed 值设置为字符串与布尔值。
最初创建元数据时,我用布尔值设置它的值:
private GridFSUploadOptions createMetadata(DateTime publishTime) {
final Document metadata = new Document();
metadata.put("processed", false);
// metadata.put("publishTime", publishTime.toString());
return new GridFSUploadOptions().metadata(metadata);
}
然后我检查一个布尔值:
public GridFSFindIterable getUnprocessedFiles() {
return gridFSBucketFactory.getGridFSBucket()
.find(eq("metadata.processed", false));
}
但是在使用 "fs.files" MongoCollection 更新元数据时,我错误地在此处的布尔值周围添加了引号:
private static final String UPDATE_STR =
"'{'\"$set\": '{'\"metadata.processed\": \"{0}\"'}}'";
这导致元数据值被保存为字符串而不是布尔值。