From ce5590228f684de94c75d2f8f77d1c35ff88aa89 Mon Sep 17 00:00:00 2001 From: Anwar khanfir <93767376+akhanfir@users.noreply.github.com> Date: Mon, 7 Aug 2023 17:04:32 +0100 Subject: [PATCH] fix: [NEWS] Filtered articles aren't retreived if they contain links - EXO-64780 (#895) (#902) Prior to this change, when create an article with a link, open the news app, and filter articles by the keyword of the link, that article is not picked up in the filtered list. To fix this problem, add in the SQL query the search for this term in the property exo:body. After this change, this article is listed in the results. --- .../news/connector/NewsSearchConnector.java | 35 ------ .../news/queryBuilder/NewsQueryBuilder.java | 38 ++++++- .../connector/NewsSearchConnectorTest.java | 104 ------------------ .../queryBuilder/NewsQueryBuilderTest.java | 75 ++++++++++++- 4 files changed, 109 insertions(+), 143 deletions(-) diff --git a/services/src/main/java/org/exoplatform/news/connector/NewsSearchConnector.java b/services/src/main/java/org/exoplatform/news/connector/NewsSearchConnector.java index dbdba4fa22..c72921186d 100644 --- a/services/src/main/java/org/exoplatform/news/connector/NewsSearchConnector.java +++ b/services/src/main/java/org/exoplatform/news/connector/NewsSearchConnector.java @@ -30,7 +30,6 @@ public class NewsSearchConnector extends SearchServiceConnector { private static final Log LOG = ExoLogger.getLogger(NewsSearchConnector.class.getName()); - private static final String FUZZY_SEARCH_SYNTAX = "~0.6"; public NewsSearchConnector(InitParams initParams,SessionProviderService sessionProviderService,RepositoryService repositoryService) throws Exception { super(initParams); @@ -60,9 +59,6 @@ public List search(NewsFilter filter, Session session = sessionProvider.getSession(repositoryService.getCurrentRepository().getConfiguration().getDefaultWorkspaceName(), repositoryService.getCurrentRepository()); - if (filter.getSearchText() != null) { - filter.setSearchText(this.addFuzzySyntaxAndOR(filter.getSearchText().trim().toLowerCase())); - } List res = new ArrayList<>(); NewsQueryBuilder queryBuilder = new NewsQueryBuilder(); try { @@ -93,35 +89,4 @@ public List search(NewsFilter filter, } return res; } - - protected String addFuzzySyntaxAndOR(String text) { - StringBuilder fuzzyText = new StringBuilder(); - boolean quote = false; - for (int i =0; i < text.length(); i++) { - if (text.charAt(i) == ' ' && text.charAt(i-1) != '"' && !quote) { - fuzzyText = fuzzyText.append(FUZZY_SEARCH_SYNTAX); - if(i != text.length()-1) { - fuzzyText = fuzzyText.append(" OR "); - } - } else if (text.charAt(i) == '"' && !quote){ - fuzzyText = fuzzyText.append("\""); - quote = true; - } else if (text.charAt(i) == '"' && quote){ - if (i != text.length()-1) { - quote = false; - fuzzyText = fuzzyText.append("\"").append(FUZZY_SEARCH_SYNTAX); - if(i != text.length()-1) { - fuzzyText = fuzzyText.append(" OR "); - } - } else { - quote = false; - fuzzyText = fuzzyText.append("\""); - } - } - else{ - fuzzyText = fuzzyText.append(text.charAt(i)); - } - } - return fuzzyText.append(FUZZY_SEARCH_SYNTAX).toString(); - } } diff --git a/services/src/main/java/org/exoplatform/news/queryBuilder/NewsQueryBuilder.java b/services/src/main/java/org/exoplatform/news/queryBuilder/NewsQueryBuilder.java index f205a37950..7939aa8d7e 100644 --- a/services/src/main/java/org/exoplatform/news/queryBuilder/NewsQueryBuilder.java +++ b/services/src/main/java/org/exoplatform/news/queryBuilder/NewsQueryBuilder.java @@ -24,6 +24,9 @@ public class NewsQueryBuilder { private final static String PLATFORM_WEB_CONTRIBUTORS_GROUP = "/platform/web-contributors"; + private static final String FUZZY_SEARCH_SYNTAX = "~0.6"; + + /** * builds query for news actions * @@ -53,8 +56,10 @@ public StringBuilder buildQuery(NewsFilter filter) throws Exception { } } if (filter.getSearchText() != null && !filter.getSearchText().equals("")) { + String fuzzyText = this.addFuzzySyntaxAndOR(filter.getSearchText().trim().toLowerCase()); + String escapedQuoteFuzzyText = fuzzyText.replace("'", "''").replace("\"", "\"\""); String escapedQuoteSearchText = filter.getSearchText().replace("'", "''").replace("\"", "\"\""); - sqlQuery.append("CONTAINS(.,'").append(escapedQuoteSearchText).append("')"); + sqlQuery.append("(CONTAINS(.,'").append(escapedQuoteFuzzyText).append("') OR (exo:body LIKE '%").append(escapedQuoteSearchText).append("%'))"); if (filter.getTagNames() != null && !filter.getTagNames().isEmpty()){ sqlQuery.append(" OR ("); for (String tagName : filter.getTagNames()) { @@ -126,4 +131,35 @@ public StringBuilder buildQuery(NewsFilter filter) throws Exception { } return sqlQuery; } + + protected String addFuzzySyntaxAndOR(String text) { + StringBuilder fuzzyText = new StringBuilder(); + boolean quote = false; + for (int i =0; i < text.length(); i++) { + if (text.charAt(i) == ' ' && text.charAt(i-1) != '"' && !quote) { + fuzzyText = fuzzyText.append(FUZZY_SEARCH_SYNTAX); + if(i != text.length()-1) { + fuzzyText = fuzzyText.append(" OR "); + } + } else if (text.charAt(i) == '"' && !quote){ + fuzzyText = fuzzyText.append("\""); + quote = true; + } else if (text.charAt(i) == '"' && quote){ + if (i != text.length()-1) { + quote = false; + fuzzyText = fuzzyText.append("\"").append(FUZZY_SEARCH_SYNTAX); + if(i != text.length()-1) { + fuzzyText = fuzzyText.append(" OR "); + } + } else { + quote = false; + fuzzyText = fuzzyText.append("\""); + } + } + else{ + fuzzyText = fuzzyText.append(text.charAt(i)); + } + } + return fuzzyText.append(FUZZY_SEARCH_SYNTAX).toString(); + } } diff --git a/services/src/test/java/org/exoplatform/news/connector/NewsSearchConnectorTest.java b/services/src/test/java/org/exoplatform/news/connector/NewsSearchConnectorTest.java index 76135e43eb..eec0896202 100644 --- a/services/src/test/java/org/exoplatform/news/connector/NewsSearchConnectorTest.java +++ b/services/src/test/java/org/exoplatform/news/connector/NewsSearchConnectorTest.java @@ -172,110 +172,6 @@ public void shouldGetResultWhenNewsExists() throws Exception { verify(rowIterator, times(1)).nextRow(); } - @Test - public void shouldAddFuzzySyntaxWhitQuotedWord() throws Exception { - // Given - String text = "\"quoted\""; - InitParams initParams = new InitParams(); - PropertiesParam propertiesParam = new PropertiesParam(); - Property searchTypeParam = new Property(); - searchTypeParam.setName(searchType); - searchTypeParam.setValue("News"); - Property displayNameParam = new Property(); - displayNameParam.setName(displayName); - displayNameParam.setValue("News"); - propertiesParam.setName("constructor.params"); - propertiesParam.addProperty(searchTypeParam); - propertiesParam.addProperty(displayNameParam); - initParams.addParameter(propertiesParam); - NewsSearchConnector newsSearchConnector = new NewsSearchConnector(initParams, sessionProviderService, repositoryService); - - // When - String result = newsSearchConnector.addFuzzySyntaxAndOR(text); - - // Then - assertNotNull(result); - assertEquals(result, "\"quoted\"~0.6"); - } - - @Test - public void shouldAddFuzzySyntaxWhenTextContainsMultiWords() throws Exception { - // Given - String text = "search text"; - InitParams initParams = new InitParams(); - PropertiesParam propertiesParam = new PropertiesParam(); - Property searchTypeParam = new Property(); - searchTypeParam.setName(searchType); - searchTypeParam.setValue("News"); - Property displayNameParam = new Property(); - displayNameParam.setName(displayName); - displayNameParam.setValue("News"); - propertiesParam.setName("constructor.params"); - propertiesParam.addProperty(searchTypeParam); - propertiesParam.addProperty(displayNameParam); - initParams.addParameter(propertiesParam); - NewsSearchConnector newsSearchConnector = new NewsSearchConnector(initParams, sessionProviderService, repositoryService); - - // When - String result = newsSearchConnector.addFuzzySyntaxAndOR(text); - - // Then - assertNotNull(result); - assertEquals(result, "search~0.6 OR text~0.6"); - } - - @Test - public void shouldAddFuzzySyntaxWhenTextContainsQuotedMultiWords() throws Exception { - // Given - String text = "\"search text\""; - InitParams initParams = new InitParams(); - PropertiesParam propertiesParam = new PropertiesParam(); - Property searchTypeParam = new Property(); - searchTypeParam.setName(searchType); - searchTypeParam.setValue("News"); - Property displayNameParam = new Property(); - displayNameParam.setName(displayName); - displayNameParam.setValue("News"); - propertiesParam.setName("constructor.params"); - propertiesParam.addProperty(searchTypeParam); - propertiesParam.addProperty(displayNameParam); - initParams.addParameter(propertiesParam); - NewsSearchConnector newsSearchConnector = new NewsSearchConnector(initParams, sessionProviderService, repositoryService); - - // When - String result = newsSearchConnector.addFuzzySyntaxAndOR(text); - - // Then - assertNotNull(result); - assertEquals(result, "\"search text\"~0.6"); - } - - @Test - public void shouldAddFuzzySyntaxWhenTextContainsMultiWordsAndQuotedOne() throws Exception { - // Given - String text = "this is a \"search text\""; - InitParams initParams = new InitParams(); - PropertiesParam propertiesParam = new PropertiesParam(); - Property searchTypeParam = new Property(); - searchTypeParam.setName(searchType); - searchTypeParam.setValue("News"); - Property displayNameParam = new Property(); - displayNameParam.setName(displayName); - displayNameParam.setValue("News"); - propertiesParam.setName("constructor.params"); - propertiesParam.addProperty(searchTypeParam); - propertiesParam.addProperty(displayNameParam); - initParams.addParameter(propertiesParam); - NewsSearchConnector newsSearchConnector = new NewsSearchConnector(initParams, sessionProviderService, repositoryService); - - // When - String result = newsSearchConnector.addFuzzySyntaxAndOR(text); - - // Then - assertNotNull(result); - assertEquals(result, "this~0.6 OR is~0.6 OR a~0.6 OR \"search text\"~0.6"); - } - @Test public void shouldGetResultWhenSearchingWithQuery() throws Exception { // Given diff --git a/services/src/test/java/org/exoplatform/news/queryBuilder/NewsQueryBuilderTest.java b/services/src/test/java/org/exoplatform/news/queryBuilder/NewsQueryBuilderTest.java index 665d48fd63..1ed4dd7ec9 100644 --- a/services/src/test/java/org/exoplatform/news/queryBuilder/NewsQueryBuilderTest.java +++ b/services/src/test/java/org/exoplatform/news/queryBuilder/NewsQueryBuilderTest.java @@ -56,7 +56,7 @@ public void shouldCreateQueryWithPinnedStateAndSearchTextAndAuthorAndOneSpaceAnd // then assertNotNull(query); - assertEquals("SELECT * FROM exo:news WHERE ( exo:archived IS NULL OR exo:archived = 'false' OR ( exo:archived = 'true' AND exo:author = 'john')) AND CONTAINS(.,'text') OR ( exo:body LIKE '%#text%' OR exo:body LIKE '%#tex%' ) AND exo:pinned = 'true' AND ( exo:spaceId = '1') AND exo:author = 'john' AND (publication:currentState = 'published' OR (publication:currentState = 'draft' AND exo:activities <> '' )) AND jcr:path LIKE '/Groups/spaces/%' ORDER BY jcr:score DESC", + assertEquals("SELECT * FROM exo:news WHERE ( exo:archived IS NULL OR exo:archived = 'false' OR ( exo:archived = 'true' AND exo:author = 'john')) AND (CONTAINS(.,'text~0.6') OR (exo:body LIKE '%text%')) OR ( exo:body LIKE '%#text%' OR exo:body LIKE '%#tex%' ) AND exo:pinned = 'true' AND ( exo:spaceId = '1') AND exo:author = 'john' AND (publication:currentState = 'published' OR (publication:currentState = 'draft' AND exo:activities <> '' )) AND jcr:path LIKE '/Groups/spaces/%' ORDER BY jcr:score DESC", query.toString()); } @@ -69,7 +69,6 @@ public void shouldCreateQueryWithPinnedStateAndAuthorAndSearchTextAndSpacesListA filter.setSearchText("text"); filter.setOrder("jcr:score"); filter.setAuthor("john"); - filter.setTagNames(Arrays.asList(new String[]{"text"})); List spaces = new ArrayList<>(); spaces.add("1"); spaces.add("2"); @@ -88,7 +87,7 @@ public void shouldCreateQueryWithPinnedStateAndAuthorAndSearchTextAndSpacesListA // then assertNotNull(query); - assertEquals("SELECT * FROM exo:news WHERE ( exo:archived IS NULL OR exo:archived = 'false' OR ( exo:archived = 'true' AND exo:author = 'john')) AND CONTAINS(.,'text') OR ( exo:body LIKE '%#text%' ) AND exo:pinned = 'true' AND ( exo:spaceId = '1' OR exo:spaceId = '2' OR exo:spaceId = '3') AND exo:author = 'john' AND (publication:currentState = 'published' OR (publication:currentState = 'draft' AND exo:activities <> '' )) AND jcr:path LIKE '/Groups/spaces/%' ORDER BY jcr:score DESC", + assertEquals("SELECT * FROM exo:news WHERE ( exo:archived IS NULL OR exo:archived = 'false' OR ( exo:archived = 'true' AND exo:author = 'john')) AND (CONTAINS(.,'text~0.6') OR (exo:body LIKE '%text%'))AND exo:pinned = 'true' AND ( exo:spaceId = '1' OR exo:spaceId = '2' OR exo:spaceId = '3') AND exo:author = 'john' AND (publication:currentState = 'published' OR (publication:currentState = 'draft' AND exo:activities <> '' )) AND jcr:path LIKE '/Groups/spaces/%' ORDER BY jcr:score DESC", query.toString()); } @@ -203,4 +202,74 @@ public void shouldCreateQueryWithStagedStateWhenCurrentUserIsAuthor() throws Exc assertEquals("SELECT * FROM exo:news WHERE publication:currentState = 'staged' AND (exo:author = 'john' OR exo:spaceId = '1' OR exo:spaceId = '2' ) AND jcr:path LIKE '/Groups/spaces/%' ORDER BY null DESC", query.toString()); } + @Test + public void shouldCreateQueryWithNoFilter() throws Exception { + // Given + NewsQueryBuilder queryBuilder = new NewsQueryBuilder(); + NewsFilter filter = new NewsFilter(); + org.exoplatform.services.security.Identity currentIdentity = new org.exoplatform.services.security.Identity("john"); + ConversationState state = new ConversationState(currentIdentity); + ConversationState.setCurrent(state); + filter = null; + // when + StringBuilder query = queryBuilder.buildQuery(filter); + + // then + assertNotNull(query); + assertEquals("SELECT * FROM exo:news WHERE ", query.toString()); + } + @Test + public void shouldAddFuzzySyntaxWhitQuotedWord() throws Exception { + // Given + String text = "\"quoted\""; + NewsQueryBuilder queryBuilder = new NewsQueryBuilder(); + + // When + String result = queryBuilder.addFuzzySyntaxAndOR(text); + + // Then + assertNotNull(result); + assertEquals(result, "\"quoted\"~0.6"); + } + + @Test + public void shouldAddFuzzySyntaxWhenTextContainsMultiWords() throws Exception { + // Given + String text = "search text"; + NewsQueryBuilder queryBuilder = new NewsQueryBuilder(); + + // When + String result = queryBuilder.addFuzzySyntaxAndOR(text); + + // Then + assertNotNull(result); + assertEquals(result, "search~0.6 OR text~0.6"); + } + + @Test + public void shouldAddFuzzySyntaxWhenTextContainsQuotedMultiWords() throws Exception { + // Given + String text = "\"search text\""; + NewsQueryBuilder queryBuilder = new NewsQueryBuilder(); + + // When + String result = queryBuilder.addFuzzySyntaxAndOR(text); + + // Then + assertNotNull(result); + assertEquals(result, "\"search text\"~0.6"); + } + @Test + public void shouldAddFuzzySyntaxWhenTextContainsMultiWordsAndQuotedOne() throws Exception { + // Given + String text = "this is a \"search text\""; + NewsQueryBuilder queryBuilder = new NewsQueryBuilder(); + + // When + String result = queryBuilder.addFuzzySyntaxAndOR(text); + + // Then + assertNotNull(result); + assertEquals(result, "this~0.6 OR is~0.6 OR a~0.6 OR \"search text\"~0.6"); + } }