我有4张桌子:
ForumPost
ForumReply
ForumComment
SearchTerms
表之间的关系:
SearchTerms表字段:
objectId
ACL
SearchString
:此列包含字符串或相关对象(ForumPost,ForumComment,ForumReply),我们将使用此列搜索任何对象或相关表objectTypeName
:这包含引用表的名称(ForumPost,ForumComment,ForumReply)]connectedObjectId
:它包含来自表ForumPost,ForumComment,ForumReply的相关对象的objectIdForumPost表字段:
objectId
replies
:(Array)此字段包含数组中所有ForumReply
的对象(附加示例)ACL
title
description
//回复样本列[{“ __type”:“指针”,“ className”:“论坛回复”,“ objectId”:“ LSVO4KwHxO”},{“ __type”:“指针”,“ className”:“论坛回复”,“ objectId”:“ EQA9Fotvp5”},{“ __type”:“指针”,“ className”:“论坛回复”,“ objectId”:“ smpfWT8fbq”}]
ForumReply表字段:
objectId
text
:回复的描述to
:这是ForumPost
表的指针searchTerm
:这是searchTerms
表的指针comments
:(数组)此字段包含数组中所有ForumComment
的对象(附加示例)
//评论字段示例][ { "__type": "Pointer", "className": "ForumComment", "objectId": "FQwqHdVX7I" }
ForumComment表字段:
objectId
text
:回复的描述to
:这是ForumReply
表的指针searchTerm
:这是searchTerms
表的指针我的目标是什么:我有一个Web表单,用户在其中输入搜索字符串,我想让所有拥有此字符串的ForumPost
都得到。搜索也将在ForumnReply
和ForumComments
中应用。因此,其回复和评论包含字符串的帖子也会出现。
我做了什么::首先,我在SearchTerms
表中运行搜索(因为该表具有所有表的搜索字符串ForumPost,ForumReply,ForumComment,所以现在我具有所有匹配对象的ID(ForumPost,ForumComment之后,我尝试使用带有结果ID的OR
查询(使用containedIn
),也尝试使用Aggregates
,但没有一个返回所有匹配的帖子。
请建议是否有更好的方法来运行此复杂搜索。
这是我的代码:
Parse.Cloud.define("searchForumPosts", function(request, response) {
isRequestLegitimate(request).then(function(result) {
if (result.legitimateRequest) {
var query = new Parse.Query("ForumPost");
var completeLength = 0;
findTextInSearchTerms(query, request.params.wildcard, "searchTerms").then(function(ids) {
var query2 = new Parse.Query("ForumPost");
if ((ids == -1 || ids.length == 0)) {
completeLength = 0;
return [];
} else {
completeLength = ids.length;
// not very efficient, if the wildcard is empty we still ask for findTextInSearchTerms, change that later on
query2.containedIn("objectId", ids);
if (request.params.pageSize && request.params.pageNumber) {
var pageSize = parseInt(request.params.pageSize);
var pageNumber = parseInt(request.params.pageNumber);
query2.limit(pageSize);
if (pageNumber > 1) {
query2.skip((pageNumber - 1) * pageSize);
}
}
// query2.include("offer");
// query2.include("offer.artist");
query2.include("creator");
query2.descending("createdAt");
query2.select("objectId", "offer","postDeleted", "title", "text", "creator", "creator.firstname", "creator.lastname", "replies");
return query2.find({
useMasterKey: true
});
}
}, function(error) {
return error;
}).then(function(foundPosts) {
console.log('foundPosts',foundPosts);
if (foundPosts.length > 1) {
var sortBy = request.params.sortBy;
if (sortBy == "artist") {
foundPosts.sort(function(a, b) {
console.log('foundPosts a',a);
console.log('foundPosts b',b);
var nameA = 'ZZZZZZZZZ';
var nameB = 'ZZZZZZZZZ';
if (a.offer) {
nameA = ((a.offer || {}).artist || {}).lastname.toUpperCase();
}
if (b.offer) {
nameB = ((b.offer || {}).artist || {}).lastname.toUpperCase();
}
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
// names must be equal
return 0;
});
} else if (sortBy == "author") {
foundPosts.sort(function(a, b) {
var nameA = 'ZZZZZZZZZ';
var nameB = 'ZZZZZZZZZ';
if (a.offer) {
nameA = ((a.offer || {}).creator || {}).lastname.toUpperCase();
}
if (b.offer) {
nameB = ((b.offer || {}).creator || {}).lastname.toUpperCase();
}
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
// names must be equal
return 0;
});
}
}
console.log('foundPostsfoundPosts',foundPosts);
var results = {};
results.completeLength = completeLength;
results.posts = foundPosts;
response.success(results);
}, function(error) {
response.error(error);
});
} else {
response.error("You must be logged in!");
}
});
});
function findTextInSearchTerms(motherQuery, wildcard, pattern, objectType) {
console.log('#findTextInSearchTerms Woldcard',wildcard);
console.log('#findTextInSearchTerms motherQuery',motherQuery);
console.log('#findTextInSearchTerms pattern',pattern);
console.log('#findTextInSearchTerms objectType',objectType);
var orQuery = null;
var promise = new Parse.Promise();
var searchTermArray = null;
var isArray = false;
var searchNeeded = true;
var filteredWildcard = []
console.log('#findTextInSearchTerms Woldcard',wildcard);
console.log('#findTextInSearchTerms motherQuery',motherQuery);
if (Array.isArray(wildcard)) {
isArray = true;
searchTermArray = wildcard
} else {
var lowerCase = (wildcard || '').toLowerCase();
lowerCase = lowerCase.trim();
// wildcard.replace(/[^a-zA-Z0-9]/g, "")
lowerCase = lowerCase.replace(/[^\w\s]/gi, '');
searchTermArray = lowerCase.split(" ");
}
if (wildcard.length < 2 && isArray == false) {
searchNeeded = false;
}
for (const element of searchTermArray) {
if((element.trim()).length > 1){
filteredWildcard.push(element);
}
}
console.log('filteredWildcard',filteredWildcard);
wildcard = filteredWildcard;
if (searchNeeded) {
console.log('#findTextInSearchTerms inside searchNeeded',wildcard);
console.log('#findTextInSearchTerms inside searchTermArray',searchTermArray);
//motherQuery.matches(pattern, regex);
if (searchTermArray.length == 1) {
console.log('#findTextInSearchTerms length == 1');
var query1 = new Parse.Query("SearchTerms");
query1.contains("searchString", searchTermArray[0]);
orQuery = Parse.Query.or(query1);
} else if (searchTermArray.length == 2) {
console.log('#findTextInSearchTerms length == 2');
var query1 = new Parse.Query("SearchTerms");
query1.contains("searchString", searchTermArray[0]);
var query2 = new Parse.Query("SearchTerms");
query2.contains("searchString", searchTermArray[1]);
orQuery = Parse.Query.or(query1, query2);
} else if (searchTermArray.length == 3) {
console.log('#findTextInSearchTerms length == 3');
var query1 = new Parse.Query("SearchTerms");
query1.contains("searchString", searchTermArray[0]);
var query2 = new Parse.Query("SearchTerms");
query2.contains("searchString", searchTermArray[1]);
var query3 = new Parse.Query("SearchTerms");
query3.contains("searchString", searchTermArray[2]);
orQuery = Parse.Query.or(query1, query2, query3);
} else if (searchTermArray.length == 4) {
console.log('#findTextInSearchTerms length == 4');
var query1 = new Parse.Query("SearchTerms");
query1.contains("searchString", searchTermArray[0]);
var query2 = new Parse.Query("SearchTerms");
query2.contains("searchString", searchTermArray[1]);
var query3 = new Parse.Query("SearchTerms");
query3.contains("searchString", searchTermArray[2]);
var query4 = new Parse.Query("SearchTerms");
query4.contains("searchString", searchTermArray[3]);
orQuery = Parse.Query.or(query1, query2, query3, query4);
} else if (searchTermArray.length == 5) {
console.log('#findTextInSearchTerms length == 5');
var query1 = new Parse.Query("SearchTerms");
query1.contains("searchString", searchTermArray[0]);
var query2 = new Parse.Query("SearchTerms");
query2.contains("searchString", searchTermArray[1]);
var query3 = new Parse.Query("SearchTerms");
query3.contains("searchString", searchTermArray[2]);
var query4 = new Parse.Query("SearchTerms");
query4.contains("searchString", searchTermArray[3]);
var query5 = new Parse.Query("SearchTerms");
query5.contains("searchString", searchTermArray[4]);
orQuery = Parse.Query.or(query1, query2, query3, query4, query5);
} else if (searchTermArray.length == 6) {
console.log('#findTextInSearchTerms length == 6');
var query1 = new Parse.Query("SearchTerms");
query1.contains("searchString", searchTermArray[0]);
var query2 = new Parse.Query("SearchTerms");
query2.contains("searchString", searchTermArray[1]);
var query3 = new Parse.Query("SearchTerms");
query3.contains("searchString", searchTermArray[2]);
var query4 = new Parse.Query("SearchTerms");
query4.contains("searchString", searchTermArray[3]);
var query5 = new Parse.Query("SearchTerms");
query5.contains("searchString", searchTermArray[4]);
var query6 = new Parse.Query("SearchTerms");
query6.contains("searchString", searchTermArray[5]);
orQuery = Parse.Query.or(query1, query2, query3, query4, query5, query6);
} else if (searchTermArray.length == 7) {
console.log('#findTextInSearchTerms length == 7');
var query1 = new Parse.Query("SearchTerms");
query1.contains("searchString", searchTermArray[0]);
var query2 = new Parse.Query("SearchTerms");
query2.contains("searchString", searchTermArray[1]);
var query3 = new Parse.Query("SearchTerms");
query3.contains("searchString", searchTermArray[2]);
var query4 = new Parse.Query("SearchTerms");
query4.contains("searchString", searchTermArray[3]);
var query5 = new Parse.Query("SearchTerms");
query5.contains("searchString", searchTermArray[4]);
var query6 = new Parse.Query("SearchTerms");
query6.contains("searchString", searchTermArray[5]);
var query7 = new Parse.Query("SearchTerms");
query7.contains("searchString", searchTermArray[6]);
orQuery = Parse.Query.or(query1, query2, query3, query4, query5, query6, query7);
} else if (searchTermArray.length == 8) {
console.log('#findTextInSearchTerms length == 8');
var query1 = new Parse.Query("SearchTerms");
query1.contains("searchString", searchTermArray[0]);
var query2 = new Parse.Query("SearchTerms");
query2.contains("searchString", searchTermArray[1]);
var query3 = new Parse.Query("SearchTerms");
query3.contains("searchString", searchTermArray[2]);
var query4 = new Parse.Query("SearchTerms");
query4.contains("searchString", searchTermArray[3]);
var query5 = new Parse.Query("SearchTerms");
query5.contains("searchString", searchTermArray[4]);
var query6 = new Parse.Query("SearchTerms");
query6.contains("searchString", searchTermArray[5]);
var query7 = new Parse.Query("SearchTerms");
query7.contains("searchString", searchTermArray[6]);
var query8 = new Parse.Query("SearchTerms");
query8.contains("searchString", searchTermArray[7]);
orQuery = Parse.Query.or(query1, query2, query3, query4, query5, query6, query7, query8);
} else if (searchTermArray.length == 9) {
console.log('#findTextInSearchTerms length == 9');
var query1 = new Parse.Query("SearchTerms");
query1.contains("searchString", searchTermArray[0]);
var query2 = new Parse.Query("SearchTerms");
query2.contains("searchString", searchTermArray[1]);
var query3 = new Parse.Query("SearchTerms");
query3.contains("searchString", searchTermArray[2]);
var query4 = new Parse.Query("SearchTerms");
query4.contains("searchString", searchTermArray[3]);
var query5 = new Parse.Query("SearchTerms");
query5.contains("searchString", searchTermArray[4]);
var query6 = new Parse.Query("SearchTerms");
query6.contains("searchString", searchTermArray[5]);
var query7 = new Parse.Query("SearchTerms");
query7.contains("searchString", searchTermArray[6]);
var query8 = new Parse.Query("SearchTerms");
query8.contains("searchString", searchTermArray[7]);
var query9 = new Parse.Query("SearchTerms");
query9.contains("searchString", searchTermArray[8]);
orQuery = Parse.Query.or(query1, query2, query3, query4, query5, query6, query7, query8, query9);
} else if (searchTermArray.length >= 10) {
console.log('#findTextInSearchTerms length == 10');
var query1 = new Parse.Query("SearchTerms");
query1.contains("searchString", searchTermArray[0]);
var query2 = new Parse.Query("SearchTerms");
query2.contains("searchString", searchTermArray[1]);
var query3 = new Parse.Query("SearchTerms");
query3.contains("searchString", searchTermArray[2]);
var query4 = new Parse.Query("SearchTerms");
query4.contains("searchString", searchTermArray[3]);
var query5 = new Parse.Query("SearchTerms");
query5.contains("searchString", searchTermArray[4]);
var query6 = new Parse.Query("SearchTerms");
query6.contains("searchString", searchTermArray[5]);
var query7 = new Parse.Query("SearchTerms");
query7.contains("searchString", searchTermArray[6]);
var query8 = new Parse.Query("SearchTerms");
query8.contains("searchString", searchTermArray[7]);
var query9 = new Parse.Query("SearchTerms");
query9.contains("searchString", searchTermArray[8]);
var query10 = new Parse.Query("SearchTerms");
query10.contains("searchString", searchTermArray[9]);
orQuery = Parse.Query.or(query1, query2, query3, query4, query5, query6, query7, query8, query9, query10);
}
console.log('#findTextInSearchTerms searchTermArray', searchTermArray);
console.log('#findTextInSearchTerms orQuery', orQuery);
if (typeof(objectType) != typeof(undefined)) {
orQuery.equalTo("objectTypeName", objectType);
}
console.log('#findTextInSearchTerms objectType after');
motherQuery.matchesQuery(pattern, orQuery);
motherQuery.limit(1000);
motherQuery.find({
useMasterKey: true
}).then(function(idArray) {
console.log('#findTextInSearchTerms idArray', idArray);
//sort objects by number of occurence
var sortedIds = idArray.map(function(obj) {
return obj.id;
});
// maybe upgrade the suggestions later...
//_.chain(idArray)
/*.countBy(function (i) {
return i.id
})
.pairs()
.sortBy(function (c) {
return -c[1]
})
.map(function (c) {
return c[0]
})
.value();
*/
promise.resolve(sortedIds);
}, function(savedObject, error) {
console.log('findTextInSearchTerms savedObject',savedObject);
console.log(' findTextInSearchTerms error',error);
promise.reject(error);
});
} else {
console.log('Inside Else of #findTextInSearchTerms');
motherQuery.limit(1000);
motherQuery.find({
useMasterKey: true
}).then(function(idArray) {
var sortedIds = idArray.map(function(obj) {
return obj.id;
});
//sort objects by number of occurence
/*var sortedIds = _.chain(idArray)
.countBy(function (i) {
return i.id
})
.pairs()
.sortBy(function (c) {
return -c[1]
})
.map(function (c) {
return c[0]
})
.value();*/
promise.resolve(sortedIds);
});
}
return promise;
}
这是一个有趣的难题。我先给你我的真实建议。然后,我将为您提供快速的答案,说明如何更改当前架构以支持您在Parse中所做的所有工作,尽管我不建议您采用这种方法。
现实世界的建议:不要将parse-server用于应用程序的此特定方面!这是一个经典的搜索难题,请按原样对待并使用非常适合此问题的类似Algolia的名称。然后,您将在三个类的解析云代码中创建一个beforeSave挂钩,并在每次发布新帖子,回复或评论时在Algolia上更新Forum索引,然后使用出色的Algolia工具为您的应用构建UI并/或网页。十分简单。您可以免费获得各种各样的花哨功能,例如,构面,评分,自动完成,词干,停用词等。(如果Algolia的成本对您来说是一个问题,您可以将Solr或弹性搜索视为开源,非商业选择)。
但是,如果您坚持只使用Parse ......,请从搜索词中删除contetObjectId并进行输入,然后在搜索词类中添加三个关系列:论坛,回复,评论,并在beforeSave钩子中分别,将帖子,回复或评论添加到适当的搜索词关系中。